neos / event-sourcing-symfony-bridge
Symfony 桥接器,用于在您的 Symfony 框架中集成事件源和 CQRS 模式。
Requires
- php: >=7.2
- neos/error-messages: *
- neos/utility-objecthandling: *
- ramsey/uuid: ^3.9
- symfony/property-access: ^5.4
- symfony/serializer: ^5.4
Suggests
- symfony/process: Needed for standalone usage
Replaces
This package is auto-updated.
Last update: 2024-08-30 01:17:59 UTC
README
为 Symfony 应用程序提供事件源应用程序接口和实现的库。
本包是 Neos.EventSourcing(为 Neos/Flow 框架创建)的 Symfony 适配器。
演示
查看 Symfony 演示存储库
https://github.com/Inchie/symfony-eventsourcing-demo.git
入门
在您的 symfony 应用程序中,使用 composer 安装此包和 neos/event-sourcing
composer require neos/event-sourcing-symfony-bridge neos/event-sourcing
设置 Doctrine 事件存储
由于一个应用程序中可能同时存在多个事件存储,因此此包不包含预配置的“默认”存储。只需几行 YAML 配置即可设置自定义存储
config/packages/neos_eventsourcing.yaml
neos_eventsourcing: stores: 'blog.events': eventTableName: blog_events 'user.events': eventTableName: user_events
在 doctrine 配置中将字符集设置为 utf8mb4,通过添加以下行。
config/packages/doctrine.yaml
doctrine: dbal: connections: default: url: '%env(resolve:DATABASE_URL)%' # IMPORTANT: You MUST configure your server version, # either here or in the DATABASE_URL env var (see .env file) server_version: '5.7' default_table_options: charset: utf8mb4 collate: utf8mb4_unicode_ci
将以下内容添加到 bundles.php
Neos\EventSourcing\SymfonyBridge\NeosEventSourcingBundle::class => ['all' => true],
要使用新配置的事件存储,完成设置还需要进行一步操作(在这种情况下是创建相应的数据库表)
php bin/console eventsourcing:store-setup
编写事件
示例事件: BlogWasCreated.php
class BlogWasCreated implements DomainEventInterface { /** * @var BlogIdentifier */ private $id; /** * @var string */ private $name; /** * @var UserIdentifier */ private $author; public function __construct( BlogIdentifier $id, string $name, UserIdentifier $author ) { $this->id = $id; $this->name = $name; $this->author = $author; } public function getId(): BlogIdentifier { return $this->id; } public function getName(): string { return $this->name; } public function getAuthor(): UserIdentifier { return $this->author; } }
<?php $uuid = $this->blogRepository->nextIdentity(); $event = new BlogWasCreated( $uuid, $command->getName(), $command->getAuthorIdentifier() ); $stream = StreamName::fromString('some-stream'); $this->eventStore->commit($stream, DomainEvents::withSingleEvent( $event ));
读取事件
<?php $streamName = StreamName::fromString('some-stream'); $eventStream = $this->eventStore->load($streamName)
对事件做出反应
为了对新事件做出反应,您需要一个事件监听器
<?php class BlogListProjector implements ProjectorInterface, EventSubscriberInterface { private $blogRepository; public function __construct(BlogRepository $blogRepository) { $this->blogRepository = $blogRepository; } public static function getSubscribedEvents() { return [ // NOTE!!! you always have to use "when*" namings, as otherwise, the EventListenerInvoker // will not properly call the right methods here. // we only use the EventSubscriber from symfony to figure out which listeners should be called. BlogWasCreated::class => ['whenBlogWasCreated'] ]; } public function whenBlogWasCreated(BlogWasCreated $event, RawEvent $rawEvent) { }
实现 EventSubscriberInterface
和 ProjectorInterface
的类的 when*()
方法将在相应的事件提交到事件存储时被调用。
注意!!!您必须始终使用 "when*" 命名,否则 EventListenerInvoker 将无法正确调用此处的方法(请参阅 neos/Neos.EventSourcing#282)
重放投影
使用以下命令可以重建投影。
bin/console eventsourcing:projection-replay eventListenerClassName eventStoreContainerId
事件和事件监听器
Neos EventSourcing 包附带其自己的事件和事件监听器实现。在 symfony 上下文中,我们无法使用此实现,原因有很多。
要为事件获取监听器(symfony 中的订阅者),我们调用 symfony 事件调度器(在 SymfonyEventPublisher 中)。
$listeners = $this->eventDispatcher->getListeners($eventClassName);
监听器由 InternalCatchUpEventListenerCommand 处理。该命令使用(Neos EventSourcing)EventListenerInvoker 调用监听器方法名称。
关于这一点,特别之处在于 EventSourcing 包使用 "when*" 命名。因此,监听器方法名称也必须以 when* 前缀开头(请参阅对事件做出反应)。
neos_eventsourcing.yml
中的所有配置选项
存储
事件存储的名称
eventTableName
:用作事件存储的数据库表名称(必需)storage
:用于持久化事件的存储引擎。默认为类名:Neos\EventSourcing\EventStore\Storage\Doctrine\DoctrineEventStorage
eventPublisherTransport
:类名。如何实现事件存储和投影之间的异步性。默认情况下使用Neos\EventSourcing\SymfonyBridge\Transport\ConsoleCommandTransport
,但也可以使用Neos\EventSourcing\SymfonyBridge\Transport\MessengerTransport
内部实现
这个包是如何构建的?我们在这里尝试提供一个概述。
composer.json
我们将neos/flow
和flowpack/jobqueue-common
替换,以确保它们没有被安装。