ildrm / servex
A microservice-based PHP framework inspired by Moleculer
Requires
- php: ^8.1
- ext-pdo: *
- firebase/php-jwt: ^6.11
- guzzlehttp/guzzle: ^7.0
- laminas/laminas-diactoros: ^2.11
- monolog/monolog: ^3.0
- psr/container: ^2.0
- psr/log: ^3.0
- psr/simple-cache: ^2.0
- vlucas/phpdotenv: ^5.5
Requires (Dev)
- phpstan/phpstan: ^1.10
- phpunit/phpunit: ^10.5
README
░▒▓███████▓▒░▒▓████████▓▒░▒▓███████▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓████████▓▒░▒▓█▓▒░░▒▓█▓▒░
░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░
░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░░▒▓█▓▒▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░
░▒▓██████▓▒░░▒▓██████▓▒░ ░▒▓███████▓▒░ ░▒▓█▓▒▒▓█▓▒░░▒▓██████▓▒░ ░▒▓██████▓▒░
░▒▓█▓▒░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░
░▒▓█▓▒░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░
░▒▓███████▓▒░░▒▓████████▓▒░▒▓█▓▒░░▒▓█▓▒░ ░▒▓██▓▒░ ░▒▓████████▓▒░▒▓█▓▒░░▒▓█▓▒░
Installation
To install the framework, use the following command:
composer require ildrm/servex
This package can run as a broker or a gateway, providing flexibility for your application architecture.
The architecture adheres to domain-driven design (DDD), segregating concerns into bounded contexts—services like UserService
and OrderService
encapsulate business logic, while infrastructural components like CacheManager
and DatabaseManager
manage persistence and performance, orchestrated by ServiceManager
and EventBus
.
Features
ildrm/servex
is a tour de force of software engineering, offering a constellation of features that resonate with the aspirations of developers, architects, engineers, and IT visionaries:
- Event-Driven Communication: A virtuoso performance in asynchronous event handling, powered by
EventBus
and seamlessly integrated with industry-leading message queues like RabbitMQ, Kafka, ActiveMQ, NATS, Redis RQ, AMQ, and HiveMQ, embodying the publish-subscribe pattern. - Dependency Injection: Implements a PSR-11 compliant
Container
, a paragon of dependency injection, ensuring loose coupling and facilitating unit testing. - Database Integration: Delivers a symphony of persistence with robust MySQL support via
Doctrine ORM
and PDO, augmented by Redis caching withPredis
, optimizing performance per caching patterns. - Authentication & Security: Orchestrates enterprise-grade security with JWT-based authentication via
AuthManager
andAuthMiddleware
, extensible for integration with Keycloak, Auth0, and OpenID Connect, adhering to security by design principles. - Scalable Design: A masterpiece of scalability, supporting microservices with
HttpTransport
for synchronous calls and message brokers for asynchronous communication, aligning with distributed systems paradigms. - GraphQL Support: Offers extensible integration with GraphQL via
webonyx/graphql-php
, enabling declarative data fetching and flexible API querying, a triumph for API design. - Testing Framework: Enshrines test-driven development with comprehensive unit tests using PHPUnit, bolstered by PHPStan for static analysis, ensuring code quality per code review standards.
- PSR Compliance: Strictly adheres to PSR standards (PSR-4, PSR-11, PSR-14, PSR-16), guaranteeing interoperability and consistency, a hallmark of software design patterns.
Integration with Message Queues
ildrm/servex
stands as a luminary in the realm of message-oriented middleware, engineered to harmonize seamlessly with an ensemble of industry-standard message queue systems, enabling asynchronous communication critical for microservices. Below, we unveil a magisterial breakdown of integration strategies, each a testament to asynchronous I/O excellence:
- Message Queue
- Integration Approach
- Considerations
Kafka
Harness rdkafka/kafka-php
or longman/kafka
to orchestrate event publishing and consumption via EventBus
, configuring topics for prodigious throughput, adhering to the publish-subscribe pattern. Extend EventBus
to leverage Kafka’s distributed log architecture, ensuring fault tolerance and scalability.
Demands a Kafka cluster, offering unparalleled performance for large-scale applications, yet necessitates meticulous PHP configuration, aligning with big data paradigms.
RabbitMQ
Integrate with php-amqplib/php-amqplib
to publish events to RabbitMQ queues and exchanges, and consume them with precision. Extend EventBus
to master AMQP protocols, enabling sophisticated complex event processing and routing, embodying enterprise messaging systems excellence.
Lightweight, reliable, and adept at complex routing, ideal for microservices with diverse message patterns, requiring an AMQP server for deployment, per message queue best practices.
ActiveMQ
Employ stomp-php/stomp-php
to connect to ActiveMQ via the STOMP protocol, extending EventBus
to publish and subscribe to queues or topics, ensuring compatibility with Java Message Service (JMS) systems, a testament to interoperability.
Supports JMS and STOMP, yet PHP support remains less prevalent, demanding meticulous library selection and rigorous software testing for legacy integrations.
NATS
Integrate with natsserver/php-nats
to harness NATS for lightweight, high-performance messaging, extending EventBus
for subjects, optimized for real-time computing scenarios, leveraging pub/sub patterns.
Exemplifies simplicity and real-time capabilities, suitable for IoT and streaming applications, yet less feature-rich for intricate routing, requiring careful architectural consideration.
Redis RQ
Leverage predis/predis
to implement Redis-based queues, extending EventBus
to utilize Redis lists or sorted sets for queuing, augmented by pub/sub for events, adhering to in-memory data grid principles.
Effortlessly integrates with existing Redis setups, yet less robust for complex patterns compared to dedicated brokers, ideal for prototyping or lightweight systems.
AMQ (Apache Qpid)
Utilize php-amqplib/php-amqplib
or STOMP libraries to connect to AMQ, extending EventBus
for AMQP or STOMP-based communication, ensuring message durability and reliability.
Resembles RabbitMQ in functionality but is less common in PHP ecosystems, necessitating thorough testing for compatibility, suitable for AMQP-centric environments.
HiveMQ
Integrate with php-mqtt/php-mqtt
for MQTT, extending EventBus
to publish and subscribe to MQTT topics, optimized for Internet of Things (IoT) and real-time applications, following the MQTT protocol.
Excels in IoT and real-time data streams, yet less aligned with traditional microservice patterns due to MQTT’s pub/sub nature, requiring specialized architectural design.
Message Queue | Integration Approach | Considerations |
---|---|---|
Kafka | Use rdkafka/kafka-php or longman/kafka for EventBus event handling, leveraging Kafka’s distributed logs for fault tolerance and scalability. |
Requires Kafka cluster, high performance for large-scale apps, but complex PHP setup per big data needs. |
RabbitMQ | Integrate with php-amqplib/php-amqplib for AMQP queues/exchanges via EventBus , enabling complex event processing. |
Lightweight, reliable, supports complex routing, needs AMQP server per message queue. |
ActiveMQ | Use stomp-php/stomp-php for STOMP, extending EventBus for JMS compatibility. |
Supports JMS/STOMP, less PHP support, needs rigorous software testing for legacy systems. |
NATS | Integrate with natsserver/php-nats for lightweight pub/sub via EventBus , optimized for real-time computing. |
Simple, real-time for IoT/streaming, but limited for complex routing. |
Redis RQ | Leverage predis/predis for Redis queues/lists, extending EventBus with pub/sub, per in-memory data grid principles. |
Easy with Redis, but less robust for complex patterns, ideal for prototyping. |
AMQ (Apache Qpid) | Use php-amqplib/php-amqplib or STOMP for AMQP, ensuring message durability. |
Similar to RabbitMQ, less PHP adoption, requires thorough testing for AMQP compatibility. |
HiveMQ | Integrate with php-mqtt/php-mqtt for MQTT topics via EventBus , optimized for Internet of Things. |
Ideal for IoT/real-time, but less suited for traditional microservices due to MQTT protocol pub/sub. |
Implementation Mastery: To integrate with any message queue, elevate the EventBus
class in src/Core/EventBus.php
with methods for publishing to and subscribing from the chosen broker. Employ corresponding PHP libraries—such as php-amqplib
for RabbitMQ or rdkafka
for Kafka—and configure connection settings in .env
or config/config.php
, adhering to software design patterns like Factory Pattern for broker instantiation.
Architectural Insight: Ensure the message broker is operational and accessible—whether via Docker, cloud services, or on-premises infrastructure—before integration. Rigorously test for latency, throughput, and reliability, aligning with software performance engineering and non-functional requirements for your microservice ecosystem.
GraphQL Integration
ildrm/servex
unveils a transformative capability to embrace GraphQL, a query language for APIs that redefines data fetching with declarative precision, empowering developers and architects to sculpt flexible, client-driven interfaces. This integration, a beacon of API design brilliance, is achieved as follows, a testament to domain-specific language mastery:
-
Install a GraphQL Library: Enlist the prowess of
webonyx/graphql-php
oroverblog/graphiql-bundle
for PHP GraphQL support. Augmentcomposer.json
with:composer require webonyx/graphql-php
-
Define Schema: Craft a GraphQL schema (e.g., in
src/Schema/UserSchema.php
) for services likeUserService
, a masterpiece of schema design and object-oriented programming:'User', 'fields' => [ 'id' => Type::int(), 'name' => Type::string(), ] ]);
-
Integrate with HttpTransport: Elevate
HttpTransport
to orchestrate GraphQL queries, routing them toServiceManager
for service invocations, a symphony of RESTful architecture and GraphQL harmony:toArray(); } // Existing HTTP logic, adhering to [HTTP protocol](https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol) $response = $this->client->post($endpoint, [ 'json' => ['method' => $method, 'params' => $params], ]); return json_decode($response->getBody()->getContents(), true); } }
-
Test and Deploy: Validate GraphQL endpoints with PHPUnit, ensuring they return expected data from services like
UserService
, following unit testing rigor. Deploy via Docker or a web server, leveraging continuous deployment for production, a pinnacle of DevOps excellence.
Architectural Brilliance: GraphQL integration enhances flexibility for client queries, but demands meticulous schema design and performance optimization for large-scale microservices, adhering to performance tuning and load balancing principles.
Security Imperative: Fortify GraphQL endpoints with AuthMiddleware
to thwart unauthorized access, especially for sensitive data like user information, aligning with security by design and OWASP best practices.
Authentication Integration (Keycloak, Auth0, OpenID)
ildrm/servex
emerges as a guardian of enterprise-grade security, offering seamless integration with preeminent authentication systems—Keycloak, Auth0, and OpenID Connect—redefining identity management for microservices. This integration, a pinnacle of single sign-on (SSO) and OAuth 2.0 sophistication, is detailed below:
- Authentication System
- Integration Approach
- Considerations
Keycloak
Enlist keycloak/keycloak-php-client
or league/oauth2-client
to orchestrate integration with Keycloak, extending AuthManager
to wield OpenID Connect tokens, validating them via Keycloak’s token endpoint with surgical precision. Configure AuthMiddleware
to scrutinize Keycloak JWTs, ensuring role-based access control (RBAC) enforcement.
Demands a Keycloak server, offering advanced RBAC and SSO capabilities, yet introduces complexity for configuration and maintenance, a challenge for enterprise architecture.
Auth0
Integrate with auth0/auth0-php
to master Auth0 JWTs, extending AuthManager
to validate tokens via Auth0’s API with elegance, and fortify AuthMiddleware
for authentication checks, adhering to OAuth 2.0 protocols.
Cloud-based and facile to configure, yet mandates an Auth0 account and may incur costs for enterprise-scale usage, aligning with SaaS paradigms.
OpenID Connect
Harness thephpleague/oauth2-client
with an OpenID provider, extending AuthManager
to validate OpenID tokens with artistry, mapping claims to user roles, and securing endpoints with AuthMiddleware
, embracing federated identity standards.
Highly interoperable, yet requires meticulous configuration of the OpenID provider and token validation logic, a challenge for identity federation architects.
Authentication System | Integration Approach | Considerations |
---|---|---|
Keycloak | Use keycloak/keycloak-php-client or league/oauth2-client for OpenID Connect, extending AuthManager for RBAC via JWTs. |
Requires Keycloak server, advanced RBAC/SSO, but complex for enterprise architecture. |
Auth0 | Integrate with auth0/auth0-php for JWT validation, extending AuthManager per OAuth 2.0. |
Cloud-based, easy setup, but costs for enterprise use, aligns with SaaS. |
OpenID Connect | Use thephpleague/oauth2-client with an OpenID provider, extending AuthManager for federated identity. |
Highly interoperable, but complex configuration, challenging for identity federation architects. |
Engineering Mastery: Refine AuthManager.php
and AuthMiddleware.php
with methods for token validation, configuring settings in .env
(e.g., KEYCLOAK_URL
, AUTH0_DOMAIN
, OPENID_ISSUER
), and adhere to security patterns like token-based authentication.
Security Vanguard: Safeguard client secrets and tokens with cryptographic rigor, and rigorously test authentication flows for vulnerabilities—such as token tampering or expiration—ensuring compliance with OWASP Top Ten and security by design doctrines.
Servex as a Message Broker
While ildrm/servex
primarily reigns as a framework for microservices, its EventBus
ascends as a virtuoso, capable of embodying a lightweight message broker for small-scale applications or serving as a proxy to external message brokers. This orchestration, a marvel of message-oriented middleware, unfolds as follows, a beacon for architects of distributed systems:
-
Role as Message Broker: Elevate
EventBus
insrc/Core/EventBus.php
to orchestrate basic pub/sub functionality, leveraging in-memory queues or Redis (viaPredis
) with virtuosity. For instance, harness Redis pub/sub or lists for queuing events, a paradigm of in-memory data grid elegance:dispatcher = new EventDispatcher(); $this->redis = $redis; } public function emit(string $eventName, array $data = []): void { $event = new class extends \Symfony\Contracts\EventDispatcher\Event { public array $data; }; $event->data = $data; $this->dispatcher->dispatch($event, $eventName); // Publish to Redis (if configured), a pinnacle of [publish-subscribe pattern](https://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern) if ($this->redis) { $this->redis->publish($eventName, json_encode($data)); } } public function on(string $eventName, callable $callback): void { $this->dispatcher->addListener($eventName, function ($event) use ($callback) { $callback($event->data); }); // Subscribe to Redis (if configured), embodying [asynchronous programming](https://en.wikipedia.org/wiki/Asynchronous_programming) if ($this->redis) { $this->redis->subscribe([$eventName], function ($message) use ($callback) { $callback(json_decode($message, true)); }); } } }
-
Service Interaction: Services like
UserService
andOrderService
engage withEventBus
in a ballet of communication, as follows, a symphony of service-oriented architecture:-
Publishing Events: A service, such as
UserService
, invokesEventBus::emit
to publish an event, a pinnacle of event sourcing:$eventBus->emit('user.created', ['id' => 1, 'name' => 'Test User']);
-
Subscribing to Events: Another service, such as
OrderService
, subscribes to events viaEventBus::on
, a masterpiece of event-driven programming:$eventBus->on('user.created', function (array $data) { echo "Processing order for user: " . $data['name'] . PHP_EOL; });
-
-
Limitations: Deploying
EventBus
as a message broker excels for small-scale or prototyping endeavors, yet for production environments, it’s imperative to enlist dedicated brokers—such as RabbitMQ or Kafka—due to their advanced features, including durability, scalability, and complex routing, aligning with enterprise messaging systems and message queue standards.
Architectural Virtuosity: For colossal applications, configure EventBus
to delegate to an external message broker, employing libraries like php-amqplib
or rdkafka
, and orchestrate queue persistence and failover externally, a pinnacle of distributed system design.
Critical Caution: Refrain from relying solely on EventBus
as a primary message broker for mission-critical systems without durability and scalability features; leverage dedicated brokers to uphold high availability and fault tolerance in production environments.
Installation
To deploy ildrm/servex
—a magnum opus of PHP microservices—requires PHP 8.1 or higher, Composer, and a harmonized environment for Redis and MySQL. Embark on this journey with the following steps, a beacon of software deployment excellence:
-
Clone the repository or procure the source code, a testament to version control:
git clone https://github.com/ildrm/servex-php.git
-
Navigate to the project directory, aligning with directory structure best practices:
cd servex
-
Install dependencies via Composer, ensuring dependency management rigor:
composer install
-
Ensure Redis and MySQL are operational—locally or within Docker—per infrastructure as code principles (see "Dependencies" below).
-
Duplicate and refine the environment file, a pinnacle of configuration management:
cp .env.example .env
Refine
.env
to orchestrate your database, Redis, and authentication credentials, adhering to environment variable security:DB_HOST=localhost DB_NAME=servex_db DB_USER=root DB_PASS= REDIS_HOST=localhost REDIS_PORT=6379 REDIS_PASSWORD= JWT_SECRET=your-secret-key-please-change-it # Optional for message brokers RABBITMQ_HOST=localhost RABBITMQ_PORT=5672 KAFKA_BOOTSTRAP_SERVERS=localhost:9092
-
Establish the database and tables (see "Database Setup" below), a cornerstone of data modeling.
-
(Optional) Leverage Docker for a containerized utopia, aligning with container orchestration:
docker-compose up -d
Usage
To wield ildrm/servex
—a masterpiece of microservice orchestration—initialize the framework via Bootstrap
and engage services through ServiceManager
. Behold this exemplar, weaving event-driven communication and message broker integration into a tapestry of service-oriented architecture:
load();
$configPath = __DIR__ . '/config/config.php';
$bootstrap = new Bootstrap($configPath);
$bootstrap->init();
$serviceManager = $bootstrap->getServiceManager();
Create a new user, a paragon of business logic
$result = $serviceManager->call('user', 'createUser', ['Malihe']);
var_dump($result);
Retrieve a user, a symphony of data access
$user = $serviceManager->call('user', 'getUser', [1]);
var_dump($user);
Emit an event with EventBus, a pinnacle of event sourcing
$eventBus = $serviceManager->getEventBus();
$eventBus->on('user.created', function (array $data) {
echo "User created: " . $data['name'] . PHP_EOL;
// Optionally publish to a message broker (e.g., RabbitMQ), adhering to [asynchronous programming](https://en.wikipedia.org/wiki/Asynchronous_programming)
$this->publishToBroker('user.created', $data); // Custom method, a model of [abstraction](https://en.wikipedia.org/wiki/Abstraction_(computer_science))
});
$eventBus->emit('user.created', ['id' => $result['id'], 'name' => 'Malihe']);
Example: Call a service via HTTP transport, a marvel of RESTful architecture
$transport = new \Servex\Core\Transport\HttpTransport();
$result = $transport->call('http://order-service/api', 'createOrder', ['userId' => $result['id']]);
var_dump($result);
Architectural Genius: For microservice deployment, orchestrate each service in a discrete process or container, leveraging Docker or Kubernetes. Configure EventBus
to integrate with message brokers for scalability and reliability, a triumph of distributed system design.
Dependencies
ildrm/servex
depends on a constellation of technologies, each a pillar of software engineering, ensuring robust performance and interoperability:
-
PHP: Version 8.1 or higher (tested with 8.3), a powerhouse of object-oriented programming and functional programming.
-
Redis: Essential for caching, deploy locally with:
sudo apt-get install redis-server redis-server
Or in Docker, a paradigm of infrastructure as code:
docker run -d --name redis -p 6379:6379 redis
-
MySQL: Crucial for database operations, install and run locally with:
sudo apt-get install mysql-server mysql -u root -p
Or via Docker, embodying containerization:
docker run -d --name mysql -e MYSQL_ROOT_PASSWORD=root -p 3306:3306 mysql
-
Composer Packages:
predis/predis
: For Redis caching (version ^2.2), a virtuoso of in-memory data grid operations.doctrine/orm
: For database ORM (version ^2.14), a titan of object-relational mapping.laminas/laminas-diactoros
: For PSR-7 HTTP messages (version ^2.11), a beacon of PSR standards.symfony/event-dispatcher
: For event handling (version ^6.0), a masterpiece of event-driven programming.firebase/php-jwt
: For JWT authentication (version ^6.11), a guardian of token-based authentication.cache/adapter-predis
: For PSR-16 Redis caching (version ^1.1, optional), enhancing caching patterns.- Other PSR-compliant packages for containers, logging, and caching, ensuring code quality.
-
Optional Message Broker Libraries:
php-amqplib/php-amqplib
: For RabbitMQ integration, a titan of message queue systems.rdkafka/kafka-php
: For Apache Kafka integration, a maestro of big data messaging.stomp-php/stomp-php
: For ActiveMQ integration, a sentinel of JMS.natsserver/php-nats
: For NATS integration, a virtuoso of real-time computing.php-mqtt/php-mqtt
: For HiveMQ (MQTT) integration, a pioneer of Internet of Things messaging.
Database Setup
To unleash ildrm/servex
and its symphony of tests, orchestrate the database and tables with precision, a cornerstone of data modeling and database design:
Create the database, a monument of relational database
CREATE DATABASE servex_db;
Use the database, aligning with schema management
USE servex_db;
Create the users table, a paragon of normalization
CREATE TABLE users (
id INT PRIMARY KEY,
name VARCHAR(255) NOT NULL
);
Insert a sample record for testing, embodying data seeding
INSERT INTO users (id, name) VALUES (1, 'Test User');
Ensure your .env
or config/config.php
resonates with your database settings, leveraging environment variables for security. For testing, deploy a test database to preserve production integrity, adhering to data isolation principles.
Testing
Conduct a virtuosic performance of unit tests with PHPUnit, ensuring ildrm/servex
’s components operate with flawless precision, a testament to test-driven development and behavior-driven development:
vendor/bin/phpunit
Before this symphony commences, ensure:
- All dependencies are installed via
composer install
, a pinnacle of dependency management. - Redis and MySQL are operational and configured correctly, aligning with infrastructure as code.
- The database and tables are established as described, embodying database testing.
- Message brokers (if utilized) are accessible and configured in
.env
, ensuring integration testing rigor.
Tests envelop core components—ServiceManager
, EventBus
, UserService
, CacheManager
, and DatabaseManager
. Employ the --verbose
flag for a detailed overture:
vendor/bin/phpunit --verbose
Testing Oracle: Should tests falter due to database, Redis, or message broker dissonance, scrutinize your .env
configuration and verify service operability, adhering to test automation best practices.
Contributing
We extend an invitation to luminaries—developers, architects, engineers, and IT visionaries—to enrich ildrm/servex
, a masterpiece of open-source collaboration. Embark on this odyssey with the following steps, a paragon of collaborative development:
-
Fork the repository on GitHub, a bastion of version control: github.com/ildrm/servex.
-
Clone your fork locally, aligning with distributed version control:
git clone https://github.com/ildrm/servex-php.git
-
Install dependencies with Composer, ensuring dependency management precision:
composer install
-
Forge a new branch for your feature or bug fix, a model of branching strategy:
git checkout -b feature/your-feature
-
Craft your changes, execute tests, and elevate code quality with PHPStan, a titan of static analysis:
vendor/bin/phpstan analyze
-
Commit your opus and propel it to your fork, adhering to commit messaging standards:
git commit -m "Add your commit message" git push origin feature/your-feature
-
Submit a pull request to the main repository, articulating your changes, testing outcomes, and relevant issues, a pinnacle of code review.
Adhere to the PSR-12 coding standards, a cornerstone of code quality, include tests for new features, and document your contributions in code and README, leveraging GitHub Actions for continuous integration and continuous deployment to guarantee compatibility with PHP 8.1+.
License
ildrm/servex
is enshrined under the MIT License, a beacon of open-source ethos. Consult the LICENSE
file in the repository for the complete text, aligning with open-source software principles.
Support and Contact
For queries, challenges, or enlightenment, engage with our community:
- Illuminate an issue on GitHub, our citadel of collaboration: github.com/ildrm/servex/issues.
- Commune with the maintainers via email at ildrm@hotmail.com.
- Join our intellectual conclave on Discord (link forthcoming).
Your insights and contributions are the lifeblood of ildrm/servex
’s ascent as a preeminent PHP microservice framework, a triumph for the global software engineering community!
Versioning
We adhere to the gospel of Semantic Versioning (SemVer), a luminary of versioning rigor. Peruse composer.json
and Git tags for version milestones (e.g., 1.0.0
), where major versions herald breaking changes, minor versions unveil features, and patch versions mend defects, ensuring backward compatibility and forward compatibility.
Project Roadmap
The trajectory of ildrm/servex
unfolds as a visionary roadmap, a beacon for future innovation, resonating with the aspirations of developers, architects, engineers, and IT luminaries:
- Integrating native support for additional message brokers (e.g., Kafka, NATS) within
EventBus
, amplifying asynchronous programming prowess. - Elevating
HttpTransport
with RESTful APIs, gRPC, and GraphQL as core features, a triumph of API design. - Crafting a comprehensive API reference and tutorials for microservice development, including message broker integration and authentication setups, embodying technical documentation excellence.
- Introducing more service exemplars (e.g.,
OrderService
,PaymentService
) with exhaustive documentation, a paradigm of domain-driven design. - Enhancing performance with Swoole or RoadRunner for real-time applications, a masterpiece of performance optimization.
- Expanding security features with native Keycloak, Auth0, and OpenID Connect integrations, a fortress of security by design.
Example Usage
To see an example of how to use this framework, visit the following repository: Servex Service Example
UserService Example
To create a new user using the UserService
, ensure that the users
table is set up in your database. You can create the table with the following SQL statement:
CREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255) NOT NULL, email VARCHAR(255) NOT NULL UNIQUE, password VARCHAR(255) NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP );
To insert a default user record, use the following SQL statement:
INSERT INTO users (name, email, password) VALUES ('Test User', 'ildrm@hotmail.com', 'password123');
You can then create a new user in your application as follows:
$result = $serviceManager->call('user', 'create', ['Test User', 'ildrm@hotmail.com', 'password123']); var_dump($result);
Examples
UserService Example
To create a new user using the UserService
, ensure that the users
table is set up in your database. You can create the table with the following SQL statement:
CREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255) NOT NULL, email VARCHAR(255) NOT NULL UNIQUE, password VARCHAR(255) NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP );
To insert a default user record, use the following SQL statement:
INSERT INTO users (name, email, password) VALUES ('Test User', 'ildrm@hotmail.com', 'password123');
You can then create a new user in your application as follows:
$result = $serviceManager->call('user', 'create', ['Test User', 'ildrm@hotmail.com', 'password123']); var_dump($result);
Service: UserService
Path: src/Services/UserService.php
Usage: src/Bootstrap.php
namespace Servex\Services; use Servex\Core\Service; use Servex\Core\Database\DatabaseManagerInterface; use Servex\Core\Cache\CacheManager; class UserService extends Service { private DatabaseManagerInterface $database; private CacheManager $cache; /** * UserService constructor * * @param DatabaseManagerInterface $database * @param CacheManager $cache * @param array $settings */ public function __construct(DatabaseManagerInterface $database, CacheManager $cache, array $settings = []) { $this->database = $database; $this->cache = $cache; parent::__construct($settings); } /** * Register service events */ protected function registerEvents(): void { if ($this->eventBus) { $this->eventBus->on('user.deleted', function(array $data) { $this->logger->info("User deleted event received", $data); // Handle user deleted event }); } } /** * Create a new user * * @param string $name * @param string $email * @param string $password * @return array */ public function create(string $name, string $email, string $password): array { $user = [ 'id' => rand(1, 1000), 'name' => $name, 'email' => $email, 'created_at' => date('Y-m-d H:i:s') ]; $this->database->query( "INSERT INTO users (id, name, email, password) VALUES (?, ?, ?, ?)", [$user['id'], $user['name'], $email, password_hash($password, PASSWORD_DEFAULT)] ); $this->cache->set("user_{$user['id']}", $user, 3600); // Emit event using the new emit method from Service base class $this->emit('created', $user); return $user; } /** * Get user by ID * * @param int $id * @return array * @throws \RuntimeException */ public function get(int $id): array { $cacheKey = "user_{$id}"; $cachedUser = $this->cache->get($cacheKey); if ($cachedUser) { return $cachedUser; } $users = $this->database->query("SELECT * FROM users WHERE id = ?", [$id]); if (!empty($users)) { $user = $users[0]; $this->cache->set($cacheKey, $user, 3600); return $user; } throw new \RuntimeException("User not found."); } /** * Update user * * @param int $id * @param array $data * @return array * @throws \RuntimeException */ public function update(int $id, array $data): array { // First get the user to make sure it exists $user = $this->get($id); // Build update query $fields = []; $values = []; foreach ($data as $key => $value) { if (in_array($key, ['name', 'email'])) { $fields[] = "{$key} = ?"; $values[] = $value; $user[$key] = $value; } } if (empty($fields)) { return $user; } $values[] = $id; $this->database->query( "UPDATE users SET " . implode(', ', $fields) . " WHERE id = ?", $values ); // Update cache $this->cache->set("user_{$id}", $user, 3600); // Emit event $this->emit('updated', $user); return $user; } /** * Delete user * * @param int $id * @return bool */ public function delete(int $id): bool { // First get the user to make sure it exists try { $user = $this->get($id); } catch (\RuntimeException $e) { return false; } $this->database->query("DELETE FROM users WHERE id = ?", [$id]); $this->cache->delete("user_{$id}"); // Emit event $this->emit('deleted', ['id' => $id]); return true; } /** * List all users * * @param int $limit * @param int $offset * @return array */ public function list(int $limit = 10, int $offset = 0): array { return $this->database->query( "SELECT * FROM users LIMIT ? OFFSET ?", [$limit, $offset] ); } }