jphooiveld / eventsauce-bundle
EventSauce Bundle
Requires
- php: ^8.1
- ext-json: *
- eventsauce/eventsauce: ^3.0
- symfony/config: ^5.4|^6.0|^7.0
- symfony/console: ^5.4|^6.0|^7.0
- symfony/dependency-injection: ^5.4|^6.0|^7.0
- symfony/http-kernel: ^5.4|^6.0|^7.0
- symfony/messenger: ^5.4|^6.0|^7.0
- symfony/string: ^5.4|^6.0|^7.0
Requires (Dev)
- eventsauce/test-utilities: ^3.0
- friendsofphp/php-cs-fixer: ^3.0
- phpstan/extension-installer: ^1.0
- phpstan/phpstan: ^1.0
- phpstan/phpstan-deprecation-rules: ^1.0
- phpstan/phpstan-phpunit: ^1.0
- phpstan/phpstan-symfony: ^1.0
- phpunit/phpunit: ^10.0
- roave/security-advisories: dev-latest
- symfony/framework-bundle: ^5.4|^6.0|^7.0
- symfony/yaml: ^5.4|^6.0|^7.0
Suggests
- eventsauce/message-repository-for-doctrine: Use Doctrine message repository to persist events with Doctrine DBAL version 3.
- eventsauce/message-repository-for-doctrine-v2: Use Doctrine message repository to persist events with Doctrine DBAL version 2.
- symfony/console: Using symfony console to create event sourcing table
- symfony/messenger: Using symfony messenger as event bus
README
信息
此包集成了EventSauce,并将它的doctrine消息存储库集成到你的symfony应用中。
强烈建议在安装此包之前了解EventSauce的工作原理或阅读官方网站(https://eventsauce.io)。
安装
将包安装到你的symfony项目中。
$ composer require jphooiveld/eventsauce-bundle
安装此包会报错,因为doctrine消息存储库缺失。你必须从EventSauce项目安装doctrine消息存储库。由于EventSauce项目同时有Doctrine DBAL版本2.x和3.x的版本,所以不能同时使用,因此你需要自己选择正确的版本。该包将自动检查已安装的消息存储库的版本并加载相应的服务。
如果你使用的是Doctrine DBAL版本3.x的项目,你必须安装该包。
$ composer require eventsauce/message-repository-for-doctrine
或者,如果你使用的是Doctrine DBAL版本2.x的项目,你必须安装该包。
$ composer require eventsauce/message-repository-for-doctrine-v2
如果你想使用symfony messenger作为分发者而不是默认的分发者,你必须安装该包。
$ composer require symfony/messenger
如果你想使用控制台命令为你生成数据库表,你必须安装该包。
$ composer require symfony/console
通常symfony应该能够自动注册该包。如果不能,你需要在配置目录中的bundles.php中添加它。
<?php return [ Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true], Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true], Jphooiveld\Bundle\EventSauceBundle\JphooiveldEventSauceBundle::class => ['all' => true], ];
配置
jphooiveld_event_sauce: time_of_recording: # The timezone to use for recorded messages, defaults to PHP ini setting. timezone: UTC messenger: # Use symfony messenger instead of EventSauce's default dispatcher (needs package symfony/messenger installed). enabled: false # The name of the messenger command bus service to use. service_bus: messenger.bus.events message_repository: # Override if you don't want to use the default doctrine message repository but your own implementation. # If doctrine is enabled this will be ignored. service: jphooiveld_eventsauce.message_repository.doctrine doctrine: # Use doctrine as default message repository. If you turn this off you must provide your own service. enabled: true # Service that implements a doctrine connection. We assume doctrine bundle default here. connection: doctrine.dbal.default_connection # The table name in the database to store the messages. table: event # JSON encode options for the doctrine message repository json_encode_options: - !php/const JSON_PRETTY_PRINT - !php/const JSON_PRESERVE_ZERO_FRACTION # Table schema to use: default (EventSauce 1.x) or legacy (EventSauce 0.8.x) table_schema: default # UUID encpder to use: string or binary uuid_encoder: string # Configure provided aggregate roots to use the default repository implementations as created by the bundle aggregates: - App\Domain\Order snapshot_repository: # User snapshotting enabled: false # Service must point to a valid class that implements EventSauce\EventSourcing\Snapshotting\SnapshotRepository service: 'App\Infrastructure\MySnapshotRepository'
配置详情
Messenger
默认情况下,使用EventSauce的同步消息分发器。如果你启用了symfony messenger并提供了事件总线服务ID,所有消息将由messenger组件处理。
消息存储库
doctrine消息组件将自动作为依赖项安装,否则应用程序将无法正常工作。但如果你想安装另一种类型的存储库或创建自己的存储库,它很容易在服务参数中引用。如果启用了doctrine(默认启用),则将忽略此设置。
配置聚合体是绑定你的聚合体到默认EventSauce服务的消息存储库的一种简单方法。编译器传递将自动创建服务。
例如,假设你有一个名为Order的聚合根
<?php namespace App\Domain; use EventSauce\EventSourcing\AggregateRoot; class Order implements AggregateRoot { // code }
如果你将'App\Domain\Order'添加到配置中的聚合列表中,编译器传递将自动创建一个名为 jphooiveld_eventsauce.aggregate_repository.order 的服务。它还将为该存储库创建一个名为 $orderRepository 的接口绑定,接口为 EventSauce\EventSourcing\AggregateRootRepository,以便你可以将其注入到自己的服务中
假设我们有一个负责持久化订单聚合体的命令处理器。我们现在可以自动注入订单存储库以供进一步使用。
<?php namespace App\CommandHandler; use EventSauce\EventSourcing\AggregateRootRepository; class AddOrderHandler { public function __construct( private AggregateRootRepository $orderRepository, ) { } // other code }
如果你不想配置你的存储库,则不要将其添加到列表中,然后自己配置它。
当启用快照功能,且快照服务指向有效的 EventSauce\EventSourcing\Snapshotting\SnapshotRepository 实例时,每个提供的聚合体(在消息存储库配置中的聚合体下)实现 EventSauce\EventSourcing\Snapshotting\AggregateRootWithSnapshotting 将自动配置消息存储库以及快照存储库。
自动配置
EventSauce有几个接口,在安装此包时自动配置,使你的生活更加轻松。
消费者
消费者负责处理聚合事件。消息调度器负责将事件委派给消费者。您创建的每个实现 EventSauce\EventSourcing\MessageConsumer 的类都将自动接收到消息调度器的事件。然而,如果您打算使用 Symfony 消息传递器,您必须实现 __invoke 方法。为了克服这种限制,您可以使用在包中提供的 ConsumableTrait。这将确保它与 EventSauce 的默认消息调度器以及 symfony 消息传递器组件一起工作。该特性还将让消费者以与聚合存储库相同的方式处理事件。它将查找以 apply 开头且后面跟有事件名称的方法。例如,我们有一个 OrderCreated 类,它是一个表示订单已创建的事件。现在我们想要发送电子邮件通知。例如,我们可以创建一个监听器,如下所示
<?php namespace App\Service; use App\Event\OrderCreated; use EventSauce\EventSourcing\MessageConsumer; use Jphooiveld\Bundle\EventSauceBundle\ConsumableTrait; use Symfony\Component\Mailer\MailerInterface use Symfony\Component\Mime\RawMessage; class SendMailNotification implements MessageConsumer { use ConsumableTrait; public function __construct( private MailerInterface $mailer, ) { } protected function applyOrderCreated(OrderCreated $event): void { $message = new RawMessage(); // other code $this->mailer->send($message); } }
每当创建订单时,都会调用 applyOrderCreated 方法。
消息装饰器
消息装饰器允许您向消息添加额外的大头。您创建的每个实现 EventSauce\EventSourcing\MessageDecorator 的类都将自动将您定义的标题添加到持久消息。
向上转型
向上转型器可以在事件发生变化时转换消息。您创建的每个实现 EventSauce\EventSourcing\Upcasting\Upcaster 的类都将自动使用。
重写默认服务
在包中使用的所有服务实际上都是真实实现的别名。如果您想重写服务,只需创建自己的服务,并在您的 Kernel 中的构建方法中重写别名即可。
请注意,如果您开始重写服务,则可能会出现错误,因为自动配置使用了大量的默认实现。
假设您想要创建自己的类变体器,名为 App\EventSourcing\UnderscoreInflector,它实现了接口 EventSauce\EventSourcing\ClassNameInflector。您需要做的唯一一件事是在 Kernel 的构建方法中设置别名,其他相关服务将自动使用它。
<?php namespace App; use App\EventSourcing\UnderscoreInflector; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\HttpKernel\Kernel as BaseKernel; class Kernel extends BaseKernel { protected function build(ContainerBuilder $container) { $container->setAlias('jphooiveld_eventsauce.inflector', UnderscoreInflector::class); } // other code }
从 1.x 版本升级
当升级到本包的 2.x 版本时,您必须安装 EventSauce 项目中的正确 Doctrine 消息存储库包。
在 message_repository 配置下添加了一个名为 table_schema 的新选项。如果您想与当前数据库保持向后兼容,则需要将其设置为 legacy。
您可以从服务配置中删除对聚合存储库的任何绑定,因为该包已经在编译过程中通过 registerAliasForArgument 方法为您配置了这些内容。以下是我们订单聚合的示例。
services: _defaults: bind: # Line below here is no longer needed, compiler pass will take care of it # EventSauce\EventSourcing\AggregateRootRepository $orderRepository: '@jphooiveld_eventsauce.aggregate_repository.order'
某些服务配置已更改。因此,如果您手动覆盖了任何内容,您必须检查该配置。
为了升级您的代码,EventSauce 提供了一个 rector 包。有关 Rector 的更多信息,请参阅 https://github.com/EventSaucePHP/RectorFrom0to1。在 https://github.com/rectorphp/rector 上了解有关 Rector 的更多信息。
许可协议
本包受 MIT 许可协议的约束。请参阅包中的完整许可协议 https://github.com/jphooiveld/EventSauceBundle/blob/HEAD/LICENSE。