{"id":23434916,"url":"https://github.com/gpslab/cqrs","last_synced_at":"2025-10-30T07:15:53.641Z","repository":{"id":62512155,"uuid":"92310135","full_name":"gpslab/cqrs","owner":"gpslab","description":"Infrastructure for creating CQRS applications.","archived":false,"fork":false,"pushed_at":"2020-01-22T08:47:01.000Z","size":509,"stargazers_count":27,"open_issues_count":0,"forks_count":6,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-26T20:21:18.535Z","etag":null,"topics":["command","cqrs","infrastructure","middleware","php","predis","psr-11","psr-3","queue","symfony"],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gpslab.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-05-24T15:52:14.000Z","updated_at":"2024-02-10T07:58:50.000Z","dependencies_parsed_at":"2022-11-02T12:47:00.194Z","dependency_job_id":null,"html_url":"https://github.com/gpslab/cqrs","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gpslab%2Fcqrs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gpslab%2Fcqrs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gpslab%2Fcqrs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gpslab%2Fcqrs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gpslab","download_url":"https://codeload.github.com/gpslab/cqrs/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248658265,"owners_count":21140913,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["command","cqrs","infrastructure","middleware","php","predis","psr-11","psr-3","queue","symfony"],"created_at":"2024-12-23T12:33:47.936Z","updated_at":"2025-10-30T07:15:53.579Z","avatar_url":"https://github.com/gpslab.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Latest Stable Version](https://img.shields.io/packagist/v/gpslab/cqrs.svg?maxAge=3600\u0026label=stable)](https://packagist.org/packages/gpslab/cqrs)\n[![Total Downloads](https://img.shields.io/packagist/dt/gpslab/cqrs.svg?maxAge=3600)](https://packagist.org/packages/gpslab/cqrs)\n[![Build Status](https://img.shields.io/travis/gpslab/cqrs.svg?maxAge=3600)](https://travis-ci.org/gpslab/cqrs)\n[![Coverage Status](https://img.shields.io/coveralls/gpslab/cqrs.svg?maxAge=3600)](https://coveralls.io/github/gpslab/cqrs?branch=master)\n[![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/gpslab/cqrs.svg?maxAge=3600)](https://scrutinizer-ci.com/g/gpslab/cqrs/?branch=master)\n[![SensioLabs Insight](https://img.shields.io/sensiolabs/i/a7885c13-685e-49bc-b1e7-635010540f21.svg?maxAge=3600\u0026label=SLInsight)](https://insight.sensiolabs.com/projects/a7885c13-685e-49bc-b1e7-635010540f21)\n[![StyleCI](https://styleci.io/repos/92310135/shield?branch=master)](https://styleci.io/repos/92310135)\n[![License](https://img.shields.io/packagist/l/gpslab/cqrs.svg?maxAge=3600)](https://github.com/gpslab/cqrs)\n\n# CQRS\n\nInfrastructure for creating [CQRS](https://martinfowler.com/bliki/CQRS.html) applications.\n\n\u003cp align=\"center\"\u003e\u003cimg src=\"cqrs_schema.png\" alt=\"CQRS base scheme\"\u003e\u003c/p\u003e\n\n## Installation\n\nPretty simple with [Composer](http://packagist.org), run:\n\n```sh\ncomposer require gpslab/cqrs\n```\n\n## Command\n\n* **[Simple usage](docs/command/simple_usage.md)**\n* [Bus](docs/command/command_bus.md)\n* Handler\n  * [Create handler](docs/command/handler.md)\n  * Locator and Subscribers\n    * [Direct binding locator](docs/command/locator/direct_binding.md)\n    * [PSR-11 Container locator](docs/command/locator/psr-11_container.md) *([PSR-11](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-11-container.md))*\n    * [Symfony container locator](docs/command/locator/symfony_container.md) *(Symfony 3.3 [implements](http://symfony.com/blog/new-in-symfony-3-3-psr-11-containers) a [PSR-11](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-11-container.md))*\n* [Queue](docs/command/queue/queue.md)\n  * [Pull](docs/command/queue/pull/pull.md)\n    * [Memory queue](docs/command/queue/pull/memory.md)\n    * [Memory unique queue](docs/command/queue/pull/memory_unique.md)\n    * [Predis queue](docs/command/queue/pull/predis.md)\n    * [Predis unique queue](docs/command/queue/pull/predis_unique.md)\n  * [Subscribe](docs/command/queue/subscribe/subscribe.md)\n    * [Executing queue](docs/command/queue/subscribe/executing.md)\n    * [Predis queue](docs/command/queue/subscribe/predis.md)\n  * Serialize command\n    * [Optimized serializer](docs/command/queue/serialize/optimized.md)\n    * [Payload serializer](docs/command/queue/serialize/payload.md)\n* [Middleware](https://github.com/gpslab/middleware)\n* [Payload](https://github.com/gpslab/payload)\n\n### Simple usage commands\n\nCommands, in the [CQRS](https://martinfowler.com/bliki/CQRS.html) approach, are designed to change the data in the\napplication.\n\nFor example, consider the procedure for renaming an article.\n\nCreate a command to rename:\n\n```php\nuse GpsLab\\Component\\Command\\Command;\n\nclass RenameArticleCommand implements Command\n{\n    public $article_id;\n\n    public $new_name = '';\n}\n```\n\n\u003e **Note**\n\u003e\n\u003e To simplify the filling of the command, you can use [payload](https://github.com/gpslab/payload).\n\nYou can use any implementations of [callable type](http://php.net/manual/en/language.types.callable.php) as a command\nhandler. We recommend using public methods of classes as handlers. For example we use [Doctrine ORM](https://github.com/doctrine/doctrine2).\n\n```php\nuse GpsLab\\Component\\Command\\Command;\nuse Doctrine\\ORM\\EntityManagerInterface;\n\nclass RenameArticleHandler\n{\n    private $em;\n\n    public function __construct(EntityManagerInterface $em)\n    {\n        $this-\u003eem = $em;\n    }\n\n    public function handleRenameArticle(RenameArticleCommand $command): void\n    {\n        // get article by id\n        $article = $this-\u003eem-\u003egetRepository(Article::class)-\u003efind($command-\u003earticle_id);\n        $article-\u003erename($command-\u003enew_name);\n    }\n}\n```\n\nAnd now we register handler and handle command.\n\n```php\nuse GpsLab\\Component\\Command\\Bus\\HandlerLocatedCommandBus;\nuse GpsLab\\Component\\Command\\Handler\\Locator\\DirectBindingCommandHandlerLocator;\n\n// register command handler in handler locator\n$handler = new RenameArticleHandler($em);\n$locator = new DirectBindingCommandHandlerLocator();\n$locator-\u003eregisterHandler(RenameArticleCommand::class, [$handler, 'handleRenameArticle']);\n\n// create bus with command handler locator\n$bus = new HandlerLocatedCommandBus($locator);\n\n// ...\n\n// create rename article command\n$command = new RenameArticleCommand();\n$command-\u003earticle_id = $article_id;\n$command-\u003enew_name = $new_name;\n\n// handle command\n$bus-\u003ehandle($command);\n```\n\nFor the asynchronous handle a command you can use `CommandQueue`.\n\n\u003e **Note**\n\u003e\n\u003e To monitor the execution of commands, you can use [middleware](https://github.com/gpslab/middleware).\n\n\n## Query\n\n* **[Simple usage](docs/query/simple_usage.md)**\n* [Bus](docs/query/query_bus.md)\n* Handler\n  * [Create handler](docs/query/handler.md)\n  * Locator and Subscribers\n    * [Direct binding locator](docs/query/locator/direct_binding.md)\n    * [PSR-11 Container locator](docs/query/locator/psr-11_container.md) *([PSR-11](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-11-container.md))*\n    * [Symfony container locator](docs/query/locator/symfony_container.md) *(Symfony 3.3 [implements](http://symfony.com/blog/new-in-symfony-3-3-psr-11-containers) a [PSR-11](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-11-container.md))*\n* [Middleware](https://github.com/gpslab/middleware)\n* [Payload](https://github.com/gpslab/payload)\n* [Doctrine specification query](https://github.com/gpslab/specification-query)\n\n### Simple usage queries\n\nQuery, in the [CQRS](https://martinfowler.com/bliki/CQRS.html) approach, are designed to get the data in the\napplication.\n\nFor example, consider the procedure for get an article by identity.\n\nCreate a query:\n\n```php\nuse GpsLab\\Component\\Query\\Query;\n\nclass ArticleByIdentityQuery implements Query\n{\n    public $article_id;\n}\n```\n\n\u003e **Note**\n\u003e\n\u003e To simplify the filling of the query, you can use [payload](https://github.com/gpslab/payload).\n\nYou can use any implementations of [callable type](http://php.net/manual/en/language.types.callable.php) as a query\nhandler. We recommend using public methods of classes as handlers. For example we use [Doctrine ORM](https://github.com/doctrine/doctrine2).\n\n```php\nuse GpsLab\\Component\\Query\\Query;\nuse Doctrine\\ORM\\EntityManagerInterface;\n\nclass ArticleByIdentityHandler\n{\n    private $em;\n\n    public function __construct(EntityManagerInterface $em)\n    {\n        $this-\u003eem = $em;\n    }\n\n    public function handleArticleByIdentity(ArticleByIdentityQuery $query)\n    {\n        // get article by id\n        return $this-\u003eem-\u003egetRepository(Article::class)-\u003efind($query-\u003earticle_id);\n    }\n}\n```\n\nAnd now we register handler and handle query.\n\n```php\nuse GpsLab\\Component\\Query\\Bus\\HandlerLocatedQueryBus;\nuse GpsLab\\Component\\Query\\Handler\\Locator\\DirectBindingQueryHandlerLocator;\n\n// register query handler in handler locator\n$handler = new ArticleByIdentityHandler($em);\n$locator = new DirectBindingQueryHandlerLocator();\n$locator-\u003eregisterHandler(ArticleByIdentityQuery::class, [$handler, 'handleArticleByIdentity']);\n\n// create bus with query handler locator\n$bus = new HandlerLocatedQueryBus($locator);\n\n// ...\n\n// create find article query\n$query = new ArticleByIdentityQuery();\n$query-\u003earticle_id = $article_id;\n\n// handle query\n$article = $bus-\u003ehandle($query);\n```\n\n\u003e **Note**\n\u003e\n\u003e To monitor the execution of commands, you can use [middleware](https://github.com/gpslab/middleware).\n\n\n## License\n\nThis bundle is under the [MIT license](http://opensource.org/licenses/MIT). See the complete license in the file: LICENSE\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgpslab%2Fcqrs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgpslab%2Fcqrs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgpslab%2Fcqrs/lists"}