{"id":23434921,"url":"https://github.com/gpslab/domain-event-bundle","last_synced_at":"2025-04-13T03:19:58.693Z","repository":{"id":48656261,"uuid":"69584393","full_name":"gpslab/domain-event-bundle","owner":"gpslab","description":"Library to create the domain layer of your DDD application","archived":false,"fork":false,"pushed_at":"2021-07-15T15:58:27.000Z","size":115,"stargazers_count":14,"open_issues_count":1,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-26T20:21:18.558Z","etag":null,"topics":["ddd","domain-event","infrastructure","php","symfony-bundle"],"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":"2016-09-29T16:07:00.000Z","updated_at":"2021-05-31T13:05:25.000Z","dependencies_parsed_at":"2022-09-11T03:00:41.896Z","dependency_job_id":null,"html_url":"https://github.com/gpslab/domain-event-bundle","commit_stats":null,"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gpslab%2Fdomain-event-bundle","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gpslab%2Fdomain-event-bundle/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gpslab%2Fdomain-event-bundle/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gpslab%2Fdomain-event-bundle/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gpslab","download_url":"https://codeload.github.com/gpslab/domain-event-bundle/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248218307,"owners_count":21066871,"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":["ddd","domain-event","infrastructure","php","symfony-bundle"],"created_at":"2024-12-23T12:34:00.280Z","updated_at":"2025-04-13T03:19:58.674Z","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/domain-event-bundle.svg?maxAge=3600\u0026label=stable)](https://packagist.org/packages/gpslab/domain-event-bundle)\n[![PHP Version Support](https://img.shields.io/travis/php-v/gpslab/domain-event-bundle.svg?maxAge=3600)](https://packagist.org/packages/gpslab/domain-event-bundle)\n[![Total Downloads](https://img.shields.io/packagist/dt/gpslab/domain-event-bundle.svg?maxAge=3600)](https://packagist.org/packages/gpslab/domain-event-bundle)\n[![Build Status](https://img.shields.io/github/checks-status/gpslab/domain-event-bundle/master.svg?label=build\u0026maxAge=3600)](https://travis-ci.org/gpslab/domain-event-bundle)\n[![Coverage Status](https://img.shields.io/coveralls/gpslab/domain-event-bundle.svg?maxAge=3600)](https://coveralls.io/github/gpslab/domain-event-bundle?branch=master)\n[![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/gpslab/domain-event-bundle.svg?maxAge=3600)](https://scrutinizer-ci.com/g/gpslab/domain-event-bundle/?branch=master)\n[![License](https://img.shields.io/packagist/l/gpslab/domain-event-bundle.svg?maxAge=3600)](https://github.com/gpslab/domain-event-bundle)\n\nDomain event bundle\n===================\n\nBundle to create the domain layer of your [Domain-driven design (DDD)](https://en.wikipedia.org/wiki/Domain-driven_design) application.\n\nThis [Symfony](https://symfony.com/) bundle is a wrapper for [gpslab/domain-event](https://github.com/gpslab/domain-event), look it for more details.\n\nInstallation\n------------\n\nPretty simple with [Composer](http://packagist.org), run:\n\n```sh\ncomposer req gpslab/domain-event-bundle\n```\n\nConfiguration\n-------------\n\nExample configuration\n\n```yml\ngpslab_domain_event:\n    # Event bus service\n    # Support 'listener_located', 'queue' or a custom service\n    # As a default used 'listener_located'\n    bus: 'listener_located'\n\n    # Event queue service\n    # Support 'pull_memory', 'subscribe_executing' or a custom service\n    # As a default used 'pull_memory'\n    queue: 'pull_memory'\n\n    # Event listener locator\n    # Support 'symfony', 'container', 'direct_binding' or custom service\n    # As a default used 'symfony'\n    locator: 'symfony'\n\n    # Publish domain events post a Doctrine flush event\n    # As a default used 'false'\n    publish_on_flush: true\n```\n\nUsage\n-----\n\nCreate a domain event\n\n```php\nuse GpsLab\\Domain\\Event\\Event\n\nclass PurchaseOrderCreatedEvent implements Event\n{\n    private $customer_id;\n    private $create_at;\n\n    public function __construct(CustomerId $customer_id, \\DateTimeImmutable $create_at)\n    {\n        $this-\u003ecustomer_id = $customer_id;\n        $this-\u003ecreate_at = $create_at;\n    }\n\n    public function customerId(): CustomerId\n    {\n        return $this-\u003ecustomer_id;\n    }\n\n    public function createAt(): \\DateTimeImmutable\n    {\n        return $this-\u003ecreate_at;\n    }\n}\n```\n\nRaise your event\n\n```php\nuse GpsLab\\Domain\\Event\\Aggregator\\AbstractAggregateEvents;\n\nfinal class PurchaseOrder extends AbstractAggregateEvents\n{\n    private $customer_id;\n    private $create_at;\n\n    public function __construct(CustomerId $customer_id)\n    {\n        $this-\u003ecustomer_id = $customer_id;\n        $this-\u003ecreate_at = new \\DateTimeImmutable();\n\n        $this-\u003eraise(new PurchaseOrderCreatedEvent($customer_id, $this-\u003ecreate_at));\n    }\n}\n```\n\nCreate listener\n\n```php\nuse GpsLab\\Domain\\Event\\Event;\n\nclass SendEmailOnPurchaseOrderCreated\n{\n    private $mailer;\n\n    public function __construct(\\Swift_Mailer $mailer)\n    {\n        $this-\u003emailer = $mailer;\n    }\n\n    public function onPurchaseOrderCreated(PurchaseOrderCreatedEvent $event): void\n    {\n        $message = $this-\u003emailer\n            -\u003ecreateMessage()\n            -\u003esetTo('recipient@example.com')\n            -\u003esetBody(sprintf(\n                'Purchase order created at %s for customer #%s',\n                $event-\u003ecreateAt()-\u003eformat('Y-m-d'),\n                $event-\u003ecustomerId()\n            ));\n\n        $this-\u003emailer-\u003esend($message);\n    }\n}\n```\n\nRegister event listener\n\n```yml\nservices:\n    SendEmailOnPurchaseOrderCreated:\n        arguments: [ '@mailer' ]\n        tags:\n            - { name: domain_event.listener, event: PurchaseOrderCreatedEvent, method: onPurchaseOrderCreated }\n```\n\nPublish events in listener\n\n```php\nuse GpsLab\\Domain\\Event\\Bus\\EventBus;\n\n// get event bus from DI container\n$bus = $this-\u003eget(EventBus::class);\n\n// do what you need to do on your Domain\n$purchase_order = new PurchaseOrder(new CustomerId(1));\n\n// this will clear the list of event in your AggregateEvents so an Event is trigger only once\n$events = $purchase_order-\u003epullEvents();\n\n// You can have more than one event at a time.\nforeach($events as $event) {\n    $bus-\u003epublish($event);\n}\n\n// You can use one method\n//$bus-\u003epullAndPublish($purchase_order);\n```\n\nListener method name\n--------------------\n\nYou do not need to specify the name of the event handler method. By default, the\n[__invoke](http://php.net/manual/en/language.oop5.magic.php#object.invoke) method is used.\n\n\n```php\nuse GpsLab\\Domain\\Event\\Event;\n\nclass SendEmailOnPurchaseOrderCreated\n{\n    private $mailer;\n\n    public function __construct(\\Swift_Mailer $mailer)\n    {\n        $this-\u003emailer = $mailer;\n    }\n\n    public function __invoke(PurchaseOrderCreatedEvent $event): void\n    {\n        $message = $this-\u003emailer\n            -\u003ecreateMessage()\n            -\u003esetTo('recipient@example.com')\n            -\u003esetBody(sprintf(\n                'Purchase order created at %s for customer #%s',\n                $event-\u003ecreateAt()-\u003eformat('Y-m-d'),\n                $event-\u003ecustomerId()\n            ));\n\n        $this-\u003emailer-\u003esend($message);\n    }\n}\n```\n\nRegister event listener\n\n```yml\nservices:\n    SendEmailOnPurchaseOrderCreated:\n        arguments: [ '@mailer' ]\n        tags:\n            - { name: domain_event.listener, event: PurchaseOrderCreatedEvent }\n```\n\nEvent subscribers\n-----------------\n\nCreate subscriber\n\n```php\nuse GpsLab\\Domain\\Event\\Event;\nuse GpsLab\\Domain\\Event\\Listener\\Subscriber;\n\nclass SendEmailOnPurchaseOrderCreated implements Subscriber\n{\n    private $mailer;\n\n    public function __construct(\\Swift_Mailer $mailer)\n    {\n        $this-\u003emailer = $mailer;\n    }\n\n    public static function subscribedEvents(): array\n    {\n        return [\n            PurchaseOrderCreatedEvent::class =\u003e ['onPurchaseOrderCreated'],\n        ];\n    }\n\n    public function onPurchaseOrderCreated(PurchaseOrderCreatedEvent $event): void\n    {\n        $message = $this-\u003emailer\n            -\u003ecreateMessage()\n            -\u003esetTo('recipient@example.com')\n            -\u003esetBody(sprintf(\n                'Purchase order created at %s for customer #%s',\n                $event-\u003ecreateAt()-\u003eformat('Y-m-d'),\n                $event-\u003ecustomerId()\n            ));\n\n        $this-\u003emailer-\u003esend($message);\n    }\n}\n```\n\nRegister event subscriber\n\n```yml\nservices:\n    SendEmailOnPurchaseOrderCreated:\n        arguments: [ '@mailer' ]\n        tags:\n            - { name: domain_event.subscriber }\n```\n\nUse pull Predis queue\n---------------------\n\nInstall [Predis](https://github.com/nrk/predis) with [Composer](http://packagist.org), run:\n\n```sh\ncomposer require predis/predis\n```\n\nRegister services:\n\n```yml\nservices:\n    # Predis\n    Predis\\Client:\n        arguments: [ '127.0.0.1' ]\n\n    # Events serializer for queue\n    GpsLab\\Domain\\Event\\Queue\\Serializer\\SymfonySerializer:\n        arguments: [ '@serializer', 'json' ]\n\n    # Predis event queue\n    GpsLab\\Domain\\Event\\Queue\\Pull\\PredisPullEventQueue:\n        arguments:\n            - '@Predis\\Client'\n            - '@GpsLab\\Domain\\Event\\Queue\\Serializer\\SymfonySerializer'\n            - '@logger'\n            - 'event_queue_name'\n```\n\nChange config for use custom queue:\n\n```yml\ngpslab_domain_event:\n    queue: 'GpsLab\\Domain\\Event\\Queue\\Pull\\PredisPullEventQueue'\n```\n\nAnd now you can use custom queue:\n\n```php\nuse GpsLab\\Domain\\Event\\Queue\\EventQueue;\n\n$container-\u003eget(EventQueue::class)-\u003epublish($domain_event);\n```\n\nIn latter pull events from queue:\n\n```php\nuse GpsLab\\Domain\\Event\\Queue\\EventQueue;\n\n$queue = $container-\u003eget(EventQueue::class);\n$bus = $container-\u003eget(EventQueue::class);\n\nwhile ($event = $queue-\u003epull()) {\n    $bus-\u003epublish($event);\n}\n```\n\nUse Predis subscribe queue\n--------------------------\n\nInstall [Predis PubSub](https://github.com/Superbalist/php-pubsub-redis) adapter with [Composer](http://packagist.org), run:\n\n```sh\ncomposer require superbalist/php-pubsub-redis\n```\n\nRegister services:\n\n```yml\nservices:\n    # Predis\n    Predis\\Client:\n        arguments: [ '127.0.0.1' ]\n\n    # Predis PubSub adapter\n    Superbalist\\PubSub\\Redis\\RedisPubSubAdapter:\n        arguments: [ '@Predis\\Client' ]\n\n    # Events serializer for queue\n    GpsLab\\Domain\\Event\\Queue\\Serializer\\SymfonySerializer:\n        arguments: [ '@serializer', 'json' ]\n\n    # Predis event queue\n    GpsLab\\Domain\\Event\\Queue\\Subscribe\\PredisSubscribeEventQueue:\n        arguments:\n            - '@Superbalist\\PubSub\\Redis\\RedisPubSubAdapter'\n            - '@GpsLab\\Domain\\Event\\Queue\\Serializer\\SymfonySerializer'\n            - '@logger'\n            - 'event_queue_name'\n```\n\nChange config for use custom queue:\n\n```yml\ngpslab_domain_event:\n    queue: 'GpsLab\\Domain\\Event\\Queue\\Subscribe\\PredisSubscribeEventQueue'\n```\n\nAnd now you can use custom queue:\n\n```php\nuse GpsLab\\Domain\\Event\\Queue\\EventQueue;\n\n$container-\u003eget(EventQueue::class)-\u003epublish($domain_event);\n```\n\nSubscribe on the queue:\n\n```php\nuse GpsLab\\Domain\\Event\\Queue\\EventQueue;\n\n$container-\u003eget(EventQueue::class)-\u003esubscribe(function (Event $event) {\n    // do somthing\n});\n```\n\n\u003e **Note**\n\u003e\n\u003e You can use subscribe handlers as a services and [tag](http://symfony.com/doc/current/service_container/tags.html) it\nfor optimize register.\n\nMany queues\n-----------\n\nYou can use many queues for separation the flows. For example, you want to handle events of different Bounded Contexts\nseparately from each other.\n\n```yml\nservices:\n    acme.domain.purchase_order.event.queue:\n        class: GpsLab\\Domain\\Event\\Queue\\Pull\\PredisPullEventQueue\n        arguments:\n            - '@Superbalist\\PubSub\\Redis\\RedisPubSubAdapter'\n            - '@GpsLab\\Domain\\Event\\Queue\\Serializer\\SymfonySerializer'\n            - '@logger'\n            - 'purchase_order_event_queue'\n\n    acme.domain.article_comment.event.queue:\n        class: GpsLab\\Domain\\Event\\Queue\\Pull\\PredisPullEventQueue\n        arguments:\n            - '@Superbalist\\PubSub\\Redis\\RedisPubSubAdapter'\n            - '@GpsLab\\Domain\\Event\\Queue\\Serializer\\SymfonySerializer'\n            - '@logger'\n            - 'article_comment_event_queue'\n```\n\nAnd now you can use a different queues.\n\nIn **Purchase order** Bounded Contexts.\n\n```php\n$event = new PurchaseOrderCreatedEvent(\n    new CustomerId(1),\n    new \\DateTimeImmutable()\n);\n\n$container-\u003eget('acme.domain.purchase_order.event.queue')-\u003epublish($event);\n```\n\nIn **Article comment** Bounded Contexts.\n\n```php\n$event = new ArticleCommentedEvent(\n    new ArticleId(1),\n    new AuthorId(1),\n    $comment\n    new \\DateTimeImmutable()\n);\n\n$container-\u003eget('acme.domain.article_comment.event.queue')-\u003epublish($event);\n```\n\n\u003e **Note**\n\u003e\n\u003e Similarly, you can split the subscribe queues.\n\nLicense\n-------\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%2Fdomain-event-bundle","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgpslab%2Fdomain-event-bundle","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgpslab%2Fdomain-event-bundle/lists"}