{"id":22496981,"url":"https://github.com/morebec/orkestra-symfony-bundle","last_synced_at":"2025-08-22T09:47:26.464Z","repository":{"id":49499667,"uuid":"359994462","full_name":"Morebec/orkestra-symfony-bundle","owner":"Morebec","description":"[READ ONLY] Symfony Bundle for the Orkestra Framework","archived":false,"fork":false,"pushed_at":"2023-03-31T18:46:57.000Z","size":103,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"2.x","last_synced_at":"2025-02-01T23:45:09.363Z","etag":null,"topics":["cqrs","ddd","event-sourcing","orkestra","php","symfony","symfony-bundle"],"latest_commit_sha":null,"homepage":"","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/Morebec.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-04-21T01:11:42.000Z","updated_at":"2022-07-25T15:52:03.000Z","dependencies_parsed_at":"2024-11-17T13:44:51.617Z","dependency_job_id":"f440eb8e-144d-4f00-aaec-ded579f89705","html_url":"https://github.com/Morebec/orkestra-symfony-bundle","commit_stats":{"total_commits":94,"total_committers":2,"mean_commits":47.0,"dds":"0.010638297872340385","last_synced_commit":"7ce668f24c125ea41633ff4f8f019e695b3cf883"},"previous_names":[],"tags_count":21,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Morebec%2Forkestra-symfony-bundle","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Morebec%2Forkestra-symfony-bundle/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Morebec%2Forkestra-symfony-bundle/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Morebec%2Forkestra-symfony-bundle/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Morebec","download_url":"https://codeload.github.com/Morebec/orkestra-symfony-bundle/tar.gz/refs/heads/2.x","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245925716,"owners_count":20694949,"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":["cqrs","ddd","event-sourcing","orkestra","php","symfony","symfony-bundle"],"created_at":"2024-12-06T20:15:07.711Z","updated_at":"2025-03-27T21:25:20.113Z","avatar_url":"https://github.com/Morebec.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Orkestra Symfony Bundle\nThis bundle integrates the Orkestra Framework with Symfony 5.\n\n[![Build Status](https://travis-ci.com/Morebec/OrkestraSymfonyBundle.svg?branch=v1.x)](https://travis-ci.com/Morebec/OrkestraSymfonyBundle)\n\n## Installation\n\n### Applications that use Symfony Flex\n\nOpen a command console, enter your project directory and execute:\n\n```console\n$ composer require morebec/orkestra-symfony-bundle\n```\n\n### Applications that don't use Symfony Flex\n\n#### Step 1: Download the Bundle\n\nOpen a command console, enter your project directory and execute the\nfollowing command to download the latest stable version of this bundle:\n\n```console\n$ composer require morebec/orkestra-symfony-bundle\n```\n\nThis command requires you to have Composer installed globally, as explained\nin the [installation chapter](https://getcomposer.org/doc/00-intro.md)\nof the Composer documentation.\n\n#### Step 2: Enable the Bundle\n\nThen, enable the bundle by adding it to the list of registered bundles\nin the `config/bundles.php` file of your project:\n\n```php\nreturn [\n    // ...\n    OrkestraSymfonyBundle::class =\u003e ['all' =\u003e true]\n];\n\n```\n\n#### Step 3: Add an Adapter\nFor persistence and infrastructure concerns, Orkestra requires adapters.\n\nInstall one of the adapters and register the classes of the adapter as services in a Module Configurator \n(see below for more information).\n \n## Usage\n\n### Creating a Module for a Bounded Context\nA Module is a logical separation of the source code. This is usually linked to the separations of DDD Bounded Contexts \naccording to the context map.\nAlthough Symfony provides a Bundle System, This bundle's Module System is tailored for the dependency injection needs of Orkestra\nbased application. It provides ways to configure services using pure PHP with a fluent API which simplifies greatly this process\nwhile still allowing all the power of Symfony.\n\n#### Step 1: Create a configuration class for the Module\n1. Create a directory under `src` with the name of your Module. E.g. `Shipping'.\n2. Inside this directory, create a class implementing the `OrkestraModuleConfiguratorInterface`.\nThis class will be used by the bundle to register the service dependencies of the module with Symfony's service container\nas well as the controller routes with the Symfony Router *(not to be confused with `MessageRoutes`)*.\n\n```php\nclass ShippingModuleConfigurator implements OrkestraModuleConfiguratorInterface\n{\n    public function configureContainer(OrkestraConfiguration $conf): void\n    {\n        $conf-\u003euseSystemClock();\n        \n        // Configure the message bus\n        $conf-\u003econfigureMessageBus(\n            (new DefaultMessageBusConfiguration())\n                -\u003ewithMiddleware(YourCustomMiddleware::class)\n        );\n        \n        // Configure the event store\n        $conf-\u003econfigureEventStore(\n            (new EventStoreConfiguration())\n                    -\u003eusingImplementation(PostgreSqlEventStore::class)\n                    -\u003edecoratedBy(UpcastingEventStoreDecorator::class)\n                    -\u003edecoratedBy(MessageBusContextEventStoreDecorator::class)\n                    -\u003ewithUpcaster(YourEventUpcaster::classs)\n        );\n        \n        // Configure Event Processing.\n        $conf-\u003econfigureEventProcessing(\n            (new EventProcessingConfiguration())\n                -\u003eusingEventStorePositionStorageImplementation(PostgreSqlEventStorePositionStorage::class)\n                \n                // Configure Projection Processing\n                -\u003econfigureProjectionProcessing(\n                    (new ProjectionProcessingConfiguration())\n                        -\u003econfigureProjectorGroup(\n                        (new ProjectorGroupConfiguration())\n                            -\u003ewithName('api')\n                            -\u003ewithProjector(YourProjector::class)\n                        )\n                )\n        );\n\n        $conf-\u003ecommandHandler(ShippingMessageHandler::class)\n            -\u003eautoroute()\n            -\u003edisableMethodRoute('__invoke')\n        ;\n\n        $conf-\u003econsoleCommand(ShippingConsoleCommand::class);\n        \n        \n        // Configure a service using Symfony's container as per usual.\n        $conf-\u003eservice(LoggerInterface::class, YourLogger::class)-\u003eargs('%env.logDir%)');\n\n    }\n\n    public function configureRoutes(RoutingConfigurator $routes): void\n    {\n    }\n}\n```\n\u003e Note: The `OrkestraConfiguration` class provides utility methods that allows to fluently define services\n\u003e with a language closer to the technical requirements of Orkestra with methods such as:\n\u003e - `$config-\u003eeventHandler(/* ... */)`\n\u003e - `$config-\u003ecommandHandler(/* ... */)`\n\u003e - `$config-\u003equeryHandler,(/* ... */)`\n\u003e - `$config-\u003eprocessManager(/* ... */)`\n\u003e - `$config-\u003eupcaster(/* ... */)`\n\u003e - `$config-\u003erepository(/* ... */)`\n\u003e - etc.\n\u003e \n\u003e These methods are shorthands for the longer versions that require using the Configuration classes.\n\n#### Step 2: Enable the Module\nThen, enable the module by adding its Configurator to the list of registered Module Configurators in the `config/modules.php` file of your project:\n```php\nreturn [\n    // ...\n    ShippingModuleConfiguratorConfigurator::class =\u003e ['all' =\u003e true],\n];\n``` \n\u003e Module Configurations are registered just like Symfony Bundles allowing you to provide the environment in which they should exist.\n\u003e If you need a different configurator on a per-environment basis, you can simply check for the environment using `$_ENV['APP_ENV]` in the configurators code\n\u003e or define different `ModuleConfigurator` classes that are environment specific.\n\n\n### Configuring Messaging\nThe messaging configuration serves to easily configure with Symfony's dependency injection the dependencies of the\n[Messaging](https://github.com/Morebec/orkestra-messaging) component.\n\nIt provides methods using a fluent API to configure, message normalization, message buses and their respective dependencies.\n\n```php\n/** @var OrkestraConfiguration $configuration */\n$configuration-\u003econfigureMessaging(\n    (new MessagingConfiguration())\n        -\u003econfigureMessageBus(\n            (new MessageBusConfiguration())\n                -\u003ewithMiddleware(YourCustomMiddleware::class)\n        )\n        -\u003econfigureMessageNormalization(\n            (new MessageNormalizerConfiguration())\n                -\u003ewithNormalizationPair(YourNormalizer::class, YourDenormalizer::class)\n        )\n        -\u003econfigureTimeoutProcessing(\n            (new TimeoutProcessingConfiguration())-\u003eusingDefaultManagerImplementation()\n        )\n);        \n```\n\n#### Configuring a Message bus\nThis bundle provides an easy way to define the middleware, message interceptors and dependencies of the message\nbus through a fluent API using the `MessageBusConfiguration` class:\n\n```php\n/** @var OrkestraConfiguration $configuration */\n$configuration-\u003econfigureMessageBus(\n    (new MessageBusConfiguration())\n        -\u003ewithMiddleware(YourCustomMiddleware::class)\n);        \n```\n\nAlternatively, there is also an implementation of this MessageBusConfiguration\nthat setups up all the default middleware of Orkestra, the `DefaultMessageBusConfiguration`:\n\n```php\n/** @var OrkestraConfiguration $configuration */\n$configuration-\u003econfigureMessageBus(\n    (MessageBusConfiguration::defaultConfiguration())\n        -\u003ewithMiddleware(YourCustomMiddleware::class)\n);\n\n// Or \n$configuration-\u003econfigureMessageBus(\n    (DefaultMessageBusConfiguration::defaultConfiguration())\n        -\u003ewithMiddleware(YourCustomMiddleware::class)\n        // Command Handlers\n        -\u003ecommandHandler(YourCommandHandler::class)\n        // Query Handlers\n        -\u003ecommandHandler(YourQueryHandler::class)\n        // Event Handlers\n        -\u003eeventHandlers(YourEventHandler::class)\n        // Timeout Handlers\n        -\u003etimeoutHandler(YourTimeoutHandler::class) \n        // Generic Message Handlers\n        -\u003eeventHandlers(YourEventHandler::class)\n        // Message Handler Interceptors\n        -\u003emessageHandlerInterceptor(YourInterceptor::class)\n        // Validators\n        -\u003emessageValidator(YourValidator::class)\n        // Authorizers\n        -\u003emessageAuthorizer(YourAuthorizer::class)\n        // Transformers\n        -\u003emessageTransformer(YourTransformer::class)\n);\n```\n\n\u003e The benefit of using the `DefaultMessageBusConfiguration` is that it allows to quickly set up a working\n\u003e message bus as well as simplifying the way to define message handlers so that they can be routed automatically.\n\u003e The same autoconfiguration applies for message validators, authorizers, and messaging transformers.\n\n##### Defining message bus dependencies in modules\nNormally the configuration of the message bus is defined in a `Core` module that serves as a cross-cutting \ndependency-builder module, however, most message handlers are usually defined in their appropriate modules.\n\nIn the case on way to define register them with the message bus is to do the following:\n\n```php\n/** @var OrkestraConfiguration $configuration */\n$configuration-\u003egetMessageBusConfiguration()\n        -\u003ewithMessageHandler(YourMessageHandler::class)\n;\n\n// Alternatively using the helper methods of the OrkestraConfiguration class\n// This will behind the scene find the message bus configuration and attach\n// the handler to it.\n$configuration\n    -\u003emessageHandler(YourMessageHandler::class)\n;\n```\n\n\n#### Configuring the Message Normalizer\nThe `MessageNormalizerInterface` can be configured to receive more `NormalizerInterface` and `DenormalizerInterface` as per your needs:\n\n```php\n/** @var OrkestraConfiguration $configuration */\n$configuration-\u003egetMessageBusConfiguration()\n        -\u003econfigureMessageNormalizer(\n            (new MessageNormalizerConfiguration())\n                -\u003eusingDefaultImplementation()\n                -\u003ewithNormalizationPair(\n                    YourNormalizer::class,\n                    YourDenormalizer::class\n                )\n                // Or\n                -\u003ewithNormalizer(YourNormalizer::class)\n                -\u003ewithDenormalizer(YourDenormalizer::class)\n        )\n;\n\n// Alternatively using the helper methods of the OrkestraConfiguration class\n// This will behind the scene find the message bus configuration and attach\n// the handler to it.\n$configuration\n    -\u003emessageHandler(YourMessageHandler::class)\n;\n```\n\n\n#### Configuring Timeout Processing\nTimeout Handlers being message handlers have to be registered with the message bus. However, they have dependencies for\ninfrastructure concerns such as processing that need to be defined in a separate configuration:\n\n```php\n/** @var OrkestraConfiguration $configuration */\n$configuration\n    -\u003econfigureTimeoutProcessing(\n        (new TimeoutProcessingConfiguration())\n            -\u003eusingManagerImplementation(TimeoutManager::class)\n            // Alternatively for the manager you can use the default implementation (TimeoutManager):\n            -\u003eusingDefaultManagerImplementation()\n            \n            // Storage\n            -\u003eusingStorageImplementation(PostgreSqlTimeoutStorage::class)\n    );\n```\n\n### Configuring the Event Store\nThe configuration of the event store follows the same configuration principles:\n\n```php\n/** @var OrkestraConfiguration $configuration */\n$configuration-\u003econfigureEventStore(\n    (new EventStoreConfiguration())\n            -\u003eusingImplementation(PostgreSqlEventStore::class)\n            \n            // Decorators priority ordered by order of declaration.\n            -\u003edecoratedBy(UpcastingEventStoreDecorator::class)\n            -\u003edecoratedBy(MessageBusContextEventStoreDecorator::class)\n            \n            // The chain is done in order of declaration.\n            // No need to define the UpcasterChain, it is automatically registered.\n            -\u003ewithUpcaster(YourEventUpcaster::classs)\n);\n```\n\n### Configuring Event Processing\nHere's a quick example of event processing configuration:\n```php\n/** @var OrkestraConfiguration $configuration */\n$configuration-\u003ecconfigureEventProcessing(\n    (new EventProcessingConfiguration())\n        \n        // Position storage for Tracking Event Processors.\n        -\u003eusingEventStorePositionStorageImplementation(PostgreSqlEventStorePositionStorage::class)\n        \n        // Configure Projection Processing\n        -\u003econfigureProjectionProcessing(\n            (new ProjectionProcessingConfiguration())\n                -\u003econfigureProjectorGroup(\n                (new ProjectorGroupConfiguration())\n                    -\u003ewithName('api')\n                    -\u003ewithProjector(YourProjector::class)\n                )\n        )\n);\n```\n\n#### Configuring Projectors\nProjecting events is part of the event processing configuration and benefits from a tailored configuration class.\nThis configuration class is used in order to easily define projectors that need to be grouped together as a single processing unit.\n\nWhen using the `ProjectionProcessingConfiguration` class, the groups will automatically be registered in a registry that can then be queried to dynamically resolve these groups.\n\nOne of the benefit is to be able to create a command like: `orkestra:projection-processor` console command that allows to\ncontrol the projector groups by name.\n\nTo configure the projector groups outside a core module you can do the following:\n```php\n// Adding a new projector group\n\n/** @var OrkestraConfiguration $configuration */\n$configuration-\u003egetProjectionProcessingConfiguration()\n    -\u003econfigureProjectorGroup(\n    (new ProjectorGroupConfiguration())\n        -\u003ewithName('api')\n        -\u003ewithProjector(YourProjector::class)\n);\n```\n\n### Adding Compiler Passes\nTo add compiler passes, one can simply use the `OrkestraConfiguration` class:\n\n```php\n/** @var OrkestraConfiguration $configuration */\n$configuration-\u003ecompilerPass(new YourCompilerPass());\n```\nAlternatively, you can rely on Symfony's `ContainerConfigurator` to register custom `Container Extensions`. \n\nFor more information on this please refer to the Official Symfony Documentation.\n\n \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmorebec%2Forkestra-symfony-bundle","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmorebec%2Forkestra-symfony-bundle","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmorebec%2Forkestra-symfony-bundle/lists"}