dsantang / domain-events-doctrine
该包提供了一个与Doctrine ORM集成的功能,以自动分发领域事件。
Requires
- php: ^8.1
- doctrine/dbal: ^3.5
- doctrine/orm: ^2.8
- dsantang/domain-events: ^0.5
- ramsey/uuid: ^4.1
- symfony/event-dispatcher: ^5.2
- symfony/event-dispatcher-contracts: ^2.4
Requires (Dev)
- doctrine/coding-standard: ^9.0
- infection/infection: ^0.26
- maglnet/composer-require-checker: ^3.2
- ocramius/package-versions: ^2.7
- phpstan/phpstan: ^1.8
- phpstan/phpstan-phpunit: ^1.1
- phpstan/phpstan-strict-rules: ^1.4
- phpunit/phpunit: ^9.5
- squizlabs/php_codesniffer: ^3.6
Suggests
- symfony/event-dispatcher: To be able to dispatch domain events via a Symfony's EventDispatcherInterface.
README
此包旨在与dsantang/domain-events一起使用,
它提供了创建应用程序领域事件所需的基本构建块。
此包提供了与Doctrine ORM的集成,
以在ORM的flush()
操作成功后自动分发记录的领域事件。
事件通过Symfony的EventDispatcherInterface
分发。
安装
建议的安装方法是使用composer
php composer.phar require dsantang/domain-events-doctrine
配置
为了自动分发您的领域事件,您首先需要将两个事件监听器添加到Doctrine的EventManager
。这些Doctrine的监听器将监听Doctrine的生命周期事件,并且只有在事务成功完成后,它们才会分发您的领域事件。
use Dsantang\DomainEventsDoctrine\EventsRecorder\DoctrineEventsRecorder; use Dsantang\DomainEventsDoctrine\Dispatcher\DoctrineEventsDispatcher; use Symfony\Component\EventDispatcher\EventDispatcher; use Doctrine\Common\EventManager; // ... $evm = new EventManager(); $dispatcher = new EventDispatcher(); // You can register here your domain event listeners to your dispatcher... $tracker = new EventsTracker(); // Make sure they share the same `EventsTracker` instance. $evm->addEventListener([Events::onFlush], new DoctrineEventsRecorder($tracker)); $evm->addEventListener([Events::postFlush], new DoctrineEventsDispatcher($tracker, $dispatcher)); // Remember to correctly wire this EventManager to your ORM.
这就完成了!您已经设置好了!现在您可以为您的$dispatcher
添加尽可能多的Symfony监听器,
并能够响应应用程序产生的领域事件。
出站模式
此库还支持出站模式的实现。
实现背后的理念是通过挂钩到Doctrine的onFlush
事件,根据应用程序的领域事件创建“出站”条目,并使用相同的DB事务安全地存储它们,以便能够将实体添加到“进行中”的事务中。
为了丰富您的领域事件并能够设置出站实体所需的所有数据,您需要创建一个Converter
类(通过实现Dsantang\DomainEventsDoctrine\Outbox\Converter
接口)。以下是一个出站事件的示例
use Dsantang\DomainEvents\DomainEvent; use Dsantang\DomainEventsDoctrine\Outbox\Converter; use Dsantang\DomainEventsDoctrine\Outbox\OutboxEntry; use Ramsey\Uuid\Uuid; use Ramsey\Uuid\UuidInterface; final class YourOutboxConverter implements Converter { public function convert(DomainEvent $domainEvent) : OutboxEntry { return new YourOutboxEntry($domainEvent); } } final class YourOutboxEntry implements OutboxEntry { /** @var DomainEvent */ private $domainEvent; public function __construct(DomainEvent $domainEvent) { $this->domainEvent = $domainEvent; } public function getName() : string { return 'OrderDispatched'; } public function getAggregateId() : UuidInterface { return Uuid::fromString('d1702762-548b-11e9-8647-d663bd873d93'); } public function getAggregateType() : string { return 'Order'; } public function getPayloadType() : string { return 'OrderStructure'; } public function getMessageKey() : string { return 'd663bd873d93'; } public function getMessageRoute() : string { return 'aggregate.order'; } public function getMessageType() : string { return 'OrderCreated'; } public function getPayload() : string { return json_encode($this->domainEvent) } public function getSchemaVersion() : int { return 1; } }
为了持久化您的出站条目,您必须在您的应用程序中创建一个扩展Dsantang\DomainEventsDoctrine\Outbox\OutboxMappedSuperclass
的Doctrine实体类。
请注意,此方法使用Doctrine的继承映射
以下是一个出站实体类的示例
namespace YourNamespace; use Doctrine\ORM\Mapping as ORM; use Dsantang\DomainEventsDoctrine\Outbox\OutboxMappedSuperclass; /** * @ORM\Entity() * @ORM\Table */ class YourOutboxEntity extends OutboxMappedSuperclass { /** * @ORM\Column(type="string") * * @var string */ private $someAdditionalField; }
以下是所需配置的示例
警告:此解决方案假定您使用Dsantang\DomainEvents\DomainEvent
来引发您的领域事件。
use Dsantang\DomainEventsDoctrine\Outbox\MapBased; use Dsantang\DomainEventsDoctrine\Outbox\OutboxMappedSuperclass; // Your class must extend OutboxMappedSuperclass $yourOutboxEntity = new YourOutboxEntity(); $mapBased = new MapBased($yourOutboxEntity); $mapBased->addConverter('YouNamespace\YourDomainEvent', new YourOutboxConverter()); // Always use with OnFlush event $evm->addEventListener([Events::onFlush], $mapBased);