morebec / orkestra-symfony-bundle
Orkestra 框架的 Symfony 扩展包
Requires
- php: >=7.4
- ext-pcntl: *
- ext-posix: *
- doctrine/annotations: 1.12.1
- morebec/orkestra-datetime: ^2.5.6
- morebec/orkestra-event-sourcing: ^2.5.6
- morebec/orkestra-messaging: ^2.5.6
- morebec/orkestra-normalization: ^2.5.6
- symfony/config: 5.*
- symfony/dependency-injection: 5.*
- symfony/framework-bundle: 5.2.*
- symfony/lock: 5.*
- symfony/validator: 5.2.*
Requires (Dev)
- friendsofphp/php-cs-fixer: ^2.16
- phpstan/phpstan: ^0.12.7
- phpunit/phpunit: ^9.5
- symfony/var-dumper: 5.*
README
此扩展包将 Orkestra 框架与 Symfony 5 集成。
安装
使用 Symfony Flex 的应用程序
打开命令行,进入您的项目目录,然后执行以下命令
$ composer require morebec/orkestra-symfony-bundle
不使用 Symfony Flex 的应用程序
步骤 1:下载扩展包
打开命令行,进入您的项目目录,并执行以下命令以下载此扩展包的最新稳定版本
$ composer require morebec/orkestra-symfony-bundle
此命令要求您已全局安装 Composer,有关详细信息,请参阅 Composer 文档的 安装章节。
步骤 2:启用扩展包
然后,通过将其添加到项目 config/bundles.php
文件中注册的扩展包列表中,启用扩展包
return [ // ... OrkestraSymfonyBundle::class => ['all' => true] ];
步骤 3:添加适配器
对于持久性和基础设施问题,Orkestra 需要适配器。
安装其中一个适配器,并将适配器的类作为服务注册到模块配置器中(以下将提供更多详细信息)。
使用
为有界上下文创建模块
模块是源代码的逻辑分离。这通常与根据上下文图划分的 DDD 有界上下文的分离相关。尽管 Symfony 提供了扩展包系统,但此扩展包的模块系统专为 Orkestra 基于应用的依赖注入需求量身定制。它提供了一种使用纯 PHP 和流畅的 API 配置服务的方法,大大简化了此过程,同时仍然允许使用所有 Symfony 的功能。
步骤 1:为模块创建配置类
- 在
src
目录下创建一个以您的模块命名的目录。例如,`Shipping'。 - 在这个目录内部,创建一个实现
OrkestraModuleConfiguratorInterface
的类。此类将被扩展包用于将模块的服务依赖关系注册到 Symfony 的服务容器中,以及将控制器路由注册到 Symfony 路由器中(请勿与MessageRoutes
混淆)。
class ShippingModuleConfigurator implements OrkestraModuleConfiguratorInterface { public function configureContainer(OrkestraConfiguration $conf): void { $conf->useSystemClock(); // Configure the message bus $conf->configureMessageBus( (new DefaultMessageBusConfiguration()) ->withMiddleware(YourCustomMiddleware::class) ); // Configure the event store $conf->configureEventStore( (new EventStoreConfiguration()) ->usingImplementation(PostgreSqlEventStore::class) ->decoratedBy(UpcastingEventStoreDecorator::class) ->decoratedBy(MessageBusContextEventStoreDecorator::class) ->withUpcaster(YourEventUpcaster::classs) ); // Configure Event Processing. $conf->configureEventProcessing( (new EventProcessingConfiguration()) ->usingEventStorePositionStorageImplementation(PostgreSqlEventStorePositionStorage::class) // Configure Projection Processing ->configureProjectionProcessing( (new ProjectionProcessingConfiguration()) ->configureProjectorGroup( (new ProjectorGroupConfiguration()) ->withName('api') ->withProjector(YourProjector::class) ) ) ); $conf->commandHandler(ShippingMessageHandler::class) ->autoroute() ->disableMethodRoute('__invoke') ; $conf->consoleCommand(ShippingConsoleCommand::class); // Configure a service using Symfony's container as per usual. $conf->service(LoggerInterface::class, YourLogger::class)->args('%env.logDir%)'); } public function configureRoutes(RoutingConfigurator $routes): void { } }
注意:
OrkestraConfiguration
类提供了实用方法,允许使用更接近 Orkestra 技术要求的语言流畅地定义服务,例如
$config->eventHandler(/* ... */)
$config->commandHandler(/* ... */)
$config->queryHandler,(/* ... */)
$config->processManager(/* ... */)
$config->upcaster(/* ... */)
$config->repository(/* ... */)
- 等等。
这些方法是对需要使用配置类进行更长时间操作的长版本的方法的简写。
步骤 2:启用模块
然后,通过将其配置器添加到项目 config/modules.php
文件中注册的模块配置器列表中,启用模块
return [ // ... ShippingModuleConfiguratorConfigurator::class => ['all' => true], ];
模块配置的注册方式与 Symfony 扩展包类似,允许您提供它们应该存在的环境。如果您需要基于环境的不同配置器,您只需在配置器代码中使用
$_ENV['APP_ENV']
检查环境,或定义特定于环境的不同ModuleConfigurator
类。
配置消息传递
消息配置用于轻松配置 消息传递 组件的依赖关系。
它提供了一种使用流畅API配置、消息标准化、消息总线及其相关依赖项的方法。
/** @var OrkestraConfiguration $configuration */ $configuration->configureMessaging( (new MessagingConfiguration()) ->configureMessageBus( (new MessageBusConfiguration()) ->withMiddleware(YourCustomMiddleware::class) ) ->configureMessageNormalization( (new MessageNormalizerConfiguration()) ->withNormalizationPair(YourNormalizer::class, YourDenormalizer::class) ) ->configureTimeoutProcessing( (new TimeoutProcessingConfiguration())->usingDefaultManagerImplementation() ) );
配置消息总线
此包通过使用MessageBusConfiguration
类,提供了一个简单的方法来定义消息中间件、消息拦截器和消息总线的依赖项。
/** @var OrkestraConfiguration $configuration */ $configuration->configureMessageBus( (new MessageBusConfiguration()) ->withMiddleware(YourCustomMiddleware::class) );
或者,还有一个名为DefaultMessageBusConfiguration
的实现,它为Orkestra设置了所有默认中间件。
/** @var OrkestraConfiguration $configuration */ $configuration->configureMessageBus( (MessageBusConfiguration::defaultConfiguration()) ->withMiddleware(YourCustomMiddleware::class) ); // Or $configuration->configureMessageBus( (DefaultMessageBusConfiguration::defaultConfiguration()) ->withMiddleware(YourCustomMiddleware::class) // Command Handlers ->commandHandler(YourCommandHandler::class) // Query Handlers ->commandHandler(YourQueryHandler::class) // Event Handlers ->eventHandlers(YourEventHandler::class) // Timeout Handlers ->timeoutHandler(YourTimeoutHandler::class) // Generic Message Handlers ->eventHandlers(YourEventHandler::class) // Message Handler Interceptors ->messageHandlerInterceptor(YourInterceptor::class) // Validators ->messageValidator(YourValidator::class) // Authorizers ->messageAuthorizer(YourAuthorizer::class) // Transformers ->messageTransformer(YourTransformer::class) );
使用
DefaultMessageBusConfiguration
的好处是,它可以快速设置一个可工作的消息总线,同时简化了定义消息处理器的途径,以便它们可以自动路由。同样的自动配置也适用于消息验证器、授权者和消息转换器。
在模块中定义消息总线依赖项
通常,消息总线的配置定义在一个Core
模块中,该模块充当一个跨切面的依赖项构建器模块,然而,大多数消息处理器通常定义在它们相应的模块中。
定义注册它们与消息总线的其中一种方法如下
/** @var OrkestraConfiguration $configuration */ $configuration->getMessageBusConfiguration() ->withMessageHandler(YourMessageHandler::class) ; // Alternatively using the helper methods of the OrkestraConfiguration class // This will behind the scene find the message bus configuration and attach // the handler to it. $configuration ->messageHandler(YourMessageHandler::class) ;
配置消息标准化器
MessageNormalizerInterface
可以根据需要配置以接收更多的NormalizerInterface
和DenormalizerInterface
。
/** @var OrkestraConfiguration $configuration */ $configuration->getMessageBusConfiguration() ->configureMessageNormalizer( (new MessageNormalizerConfiguration()) ->usingDefaultImplementation() ->withNormalizationPair( YourNormalizer::class, YourDenormalizer::class ) // Or ->withNormalizer(YourNormalizer::class) ->withDenormalizer(YourDenormalizer::class) ) ; // Alternatively using the helper methods of the OrkestraConfiguration class // This will behind the scene find the message bus configuration and attach // the handler to it. $configuration ->messageHandler(YourMessageHandler::class) ;
配置超时处理
超时处理器是消息处理器,必须注册到消息总线中。然而,它们需要定义在单独的配置中的基础设施相关的依赖项,例如处理。
/** @var OrkestraConfiguration $configuration */ $configuration ->configureTimeoutProcessing( (new TimeoutProcessingConfiguration()) ->usingManagerImplementation(TimeoutManager::class) // Alternatively for the manager you can use the default implementation (TimeoutManager): ->usingDefaultManagerImplementation() // Storage ->usingStorageImplementation(PostgreSqlTimeoutStorage::class) );
配置事件存储
事件存储的配置遵循相同的配置原则
/** @var OrkestraConfiguration $configuration */ $configuration->configureEventStore( (new EventStoreConfiguration()) ->usingImplementation(PostgreSqlEventStore::class) // Decorators priority ordered by order of declaration. ->decoratedBy(UpcastingEventStoreDecorator::class) ->decoratedBy(MessageBusContextEventStoreDecorator::class) // The chain is done in order of declaration. // No need to define the UpcasterChain, it is automatically registered. ->withUpcaster(YourEventUpcaster::classs) );
配置事件处理
以下是一个事件处理配置的快速示例
/** @var OrkestraConfiguration $configuration */ $configuration->cconfigureEventProcessing( (new EventProcessingConfiguration()) // Position storage for Tracking Event Processors. ->usingEventStorePositionStorageImplementation(PostgreSqlEventStorePositionStorage::class) // Configure Projection Processing ->configureProjectionProcessing( (new ProjectionProcessingConfiguration()) ->configureProjectorGroup( (new ProjectorGroupConfiguration()) ->withName('api') ->withProjector(YourProjector::class) ) ) );
配置投影器
事件投影是事件处理配置的一部分,并受益于一个定制的配置类。此配置类用于轻松定义需要作为单个处理单元一起分组的项目。
当使用ProjectionProcessingConfiguration
类时,组将自动注册到一个注册表中,然后可以查询该注册表以动态解析这些组。
其中一个好处是可以创建一个类似于orkestra:projection-processor
的控制台命令,该命令允许通过名称控制投影器组。
要在外部核心模块中配置投影器组,可以这样做
// Adding a new projector group /** @var OrkestraConfiguration $configuration */ $configuration->getProjectionProcessingConfiguration() ->configureProjectorGroup( (new ProjectorGroupConfiguration()) ->withName('api') ->withProjector(YourProjector::class) );
添加编译器传递
要添加编译器传递,可以使用OrkestraConfiguration
类
/** @var OrkestraConfiguration $configuration */ $configuration->compilerPass(new YourCompilerPass());
或者,您可以使用Symfony的ContainerConfigurator
来注册自定义Container Extensions
。
有关更多信息,请参阅官方Symfony文档。