dsantang/domain-events-doctrine

该包提供了一个与Doctrine ORM集成的功能,以自动分发领域事件。

v0.10.0 2023-01-04 18:00 UTC

This package is auto-updated.

Last update: 2024-09-04 21:33:58 UTC


README

CircleCI Scrutinizer Code Quality Code Coverage Build Status SymfonyInsight

此包旨在与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);