ashleydawson/domain-event-dispatcher

从单例中分发或延迟领域事件。如果你使用领域驱动设计(DDD)并且需要一个单例领域分发器来处理模型,这将非常有用。

1.0.6 2016-12-23 12:10 UTC

This package is auto-updated.

Last update: 2024-09-14 03:28:33 UTC


README

Build Status

用于领域驱动设计(DDD)的单例领域事件分发器。领域事件分发器是单例的,因此可以轻松地在模型内部使用。

安装

使用以下命令通过Composer安装

$ composer require ashleydawson/domain-event-dispatcher

基本用法

定义要分发的事件。事件类可以是任何类型,并且应该易于序列化。

<?php

namespace Acme\Event;

class MyEvent
{
}

定义事件监听器

<?php

namespace Acme\EventListener;

use Acme\Event\MyEvent;

class MyTypedEventListener
{
    // Domain event listeners must implement the __invoke() magic method with only one argument
    public function __invoke(MyEvent $event)
    {
        // Do something useful here...
    }
}

将所有内容组合在一起,添加你的监听器并分发。

<?php

require __DIR__.'/vendor/autoload.php';

use AshleyDawson\DomainEventDispatcher\DomainEventDispatcher;
use Acme\Event\MyEvent;
use Acme\EventListener\MyTypedEventListener;

// Add your listener to the dispatcher
DomainEventDispatcher::getInstance()->addListener(
    new MyTypedEventListener()
);

// Dispatch the event from within your domain, e.g. from your domain model, etc.
DomainEventDispatcher::getInstance()->dispatch(
    new MyEvent()
);

监听器类型

有两种类型的监听器

  • 通用 - 由 任何 领域事件调用。
  • 类型化 - 由相应类型的事件调用。

通用监听器

在之前的示例中,我们看到事件分发器被用于类型化事件,其中事件参数在事件监听器的 __invoke() 方法中被类型提示。通用监听器由所有事件调用,并且没有类型提示。例如

<?php

namespace Acme\EventListener;

class MyEventGeneralListener
{
    // Event is not type hinted as this is a general event listener - it will be invoked by all events
    public function __invoke($event)
    {
        // Do something useful here...
    }
}

类型化监听器

类型化监听器仅响应特定类型的领域事件

<?php

namespace Acme\EventListener;

use Acme\Event\MyEvent;

class MyEventGeneralListener
{
    // This listener will only respond to MyEvent events
    public function __invoke(MyEvent $event)
    {
        // Do something useful here...
    }
}

延迟事件

有时在应用程序流程的稍后阶段分发事件可能很有用。为此,事件可以延迟并稍后分发。

<?php

require __DIR__.'/vendor/autoload.php';

use AshleyDawson\DomainEventDispatcher\DomainEventDispatcher;
use Acme\Event\MyEvent;
use Acme\EventListener\MyTypedEventListener;

// Add your listener to the dispatcher
DomainEventDispatcher::getInstance()->addListener(
    new MyTypedEventListener()
);

// Dispatch the event from within your domain, e.g. from your domain model, etc.
DomainEventDispatcher::getInstance()->defer(
    new MyEvent()
);

// From a different level of the application, dispatch the deferred events
DomainEventDispatcher::getInstance()->dispatchDeferred();

领域事件存储

为了事件发布、通知或审计目的,您可能需要将事件存储在事件存储中。为此,只需实现 EventStoreInterface

<?php

namespace Acme\DomainEventStorage;

use AshleyDawson\DomainEventDispatcher\EventStorage\EventStoreInterface;

class InMemoryEventStore implements EventStoreInterface
{
    private $events = [];

    public function append($event)
    {
        $this->events[] = $event;
    }
}

然后配置事件分发器以使用事件存储

<?php

use AshleyDawson\DomainEventDispatcher\DomainEventDispatcher;
use Acme\DomainEventStorage\InMemoryEventStore;

DomainEventDispatcher::getInstance()->setEventStore(
    new InMemoryEventStore()
);

重要:如果配置了事件存储,事件分发器将尝试存储 所有事件。如果您不希望事件分发器存储特定事件,请在事件上实现 DisposableEventInterface

<?php

namespace Acme\Event;

use AshleyDawson\DomainEventDispatcher\EventStorage\DisposableEventInterface;

class MyDisposableEvent implements DisposableEventInterface
{
}

测试

要运行测试套件,请执行以下操作

$ php bin/phpunit