mattferris/events

事件调度器

0.4 2017-01-05 22:18 UTC

This package is auto-updated.

Last update: 2024-09-29 03:52:30 UTC


README

Build Status SensioLabsInsight

这是一个包含事件日志器的事件库。它是基于 Udi Dahan 的领域事件模式 构建的。

事件处理

实现从在您的领域创建一个继承自 MattFerris\Events\AbstractDomainEventsDomainEvents 类开始。

namespace MyDomain;

class DomainEvents extends \MattFerris\Events\AbstractDomainEvents
{
}

然后,您可以通过扩展 MattFerris\Events\Event 或实现 MattFerris\Events\EventInterface 来创建单个事件类。Event 是一个空类,所以您的事件类仍然需要提供自己的逻辑。

namespace MyDomain;

class SomeEvent extends MattFerris\Events\Event
{
    protected $someArgument;

    public function __construct($someArgument)
    {
        $this->someArgument = $someArgument;
    }

    public function getSomeArgument()
    {
        return $this->someArgument;
    }
}

要从一个领域实体内部触发/调度事件,请调用 DomainEvents::dispatch()

namespace MyDomain;

class SomeEntity
{
    public function doSomething()
    {
        // stuff happens

        // dispatch event
        DomainEvents::dispatch(new SomeEvent($argument));
    }
}

目前,尚未配置调度器,因此事件不会被任何内容处理。配置调度器可以像这样进行

$dispatcher = new MattFerris\Events\Dispatcher();
MyDomain\DomainEvents::setDispatcher($dispatcher);

现在,您可以将事件监听器添加到调度器。监听器可以是任何 callable,并且可以监听特定事件或与模式匹配的事件。要匹配特定事件,请使用完全限定类名。

$dispatcher->addListener('MyDomain.SomeEvent', function ($event) { ... });

还可以根据前缀或后缀监听事件。

// listen for all events in the `MyDomain` namespace
$dispatcher->addListener('MyDomain.', $handler);

// listen for all SomeEvent events in any domain
$dispatcher->addListener('.SomeEvent', $handler);

最后,您可以使用星号来监听所有事件。

// listen for all events
$dispatcher->addListener('*', $handler);

事件名称

为了灵活性,还可以将监听器分配给监听任意事件名称。在事件触发时,可以将事件名称传递给调度方法的 dispatch 方法。

$dispatcher->addListener('foo.bar', $listener);

$dispatcher->dispatch($event, 'foo.bar');

监听器优先级

默认情况下,所有监听器都分配了相同的优先级,并且根据它们添加的顺序调用。也可以为监听器分配优先级,以确保它们比其他监听器更早或更晚调用。优先级是在添加监听器时传递的整数,其中 0 是最高优先级。

// give the listener the highest priority
$dispatcher->addListener('*', $listener, 0);

也可以使用优先级常量分配优先级

  • PRIORITY_HIGH = 0
  • PRIORITY_NORMAL = 50
  • PRIORITY_LOW = 100
// alternatively, you can use the priority constant
$dispatcher->addListener('*', $listener, Dispatcher::PRIORITY_HIGH);

事件提供者

可以使用提供者添加事件。简单地创建一个实现 MattFerris\Provider\ProviderInterface 的类,并创建一个名为 provides() 的方法。当传递给调度器的 register() 方法时,将传递一个调度器实例,然后您可以添加监听器。

use MattFerris\Provider\ProviderInterface;
use MattFerris\Provider\ConsumerInterface;

class EventProvider implements ProviderInterface
{
    public function provides(ConsumerInterface $dispatcher)
    {
        $dispatcher->addListener('*', $listener);
        ...
    }
}

事件日志

通过使用 MattFerris\Events\Logger 来完成事件日志。构造函数接受一个 Dispatcher 实例和一个可调用的函数,该函数将传递结果日志消息,并可以将其写入日志文件、stderr 等。

$logger = new MattFerris\Events\Logger($dispatcher, function ($msg) { error_log($msg); });

就这样!所有触发的事件都将记录到 PHP 的错误日志中。默认情况下,日志消息是事件名称前加上 event: 。例如

event: MattFerris\Events\Event

您可以使用 setPrefix() 更改前缀。

$logger->setPrefix('another prefix: ');

您可以使用日志辅助函数来定制某些事件的日志消息。在您的领域创建一个名为 DomainEventLoggerHelpers 的类,并让它继承 MattFerris\Events\AbstractDomainEventLoggerHelpers。然后简单地创建静态方法来调用领域事件,其中每个方法返回要记录的字符串。这些方法应该以 on 开头,后面跟着事件名称,例如 onSomeEvent

namespace MyDomain;

class DomainEventLoggerHelpers extends MattFerris\Events\AbstractDomainEventLoggerHelpers
{
    static public function onSomeEvent(SomeEvent $e)
    {
        $foo = $e->getFoo();
        $bar = $e->getBar();

        return "SomeEvent was dispatched with values foo=$foo, bar=$bar";
    }
}

将辅助程序注册到日志记录器

MyDomain\DomainEventLoggerHelepers::addHelpers($logger);

现在,当 SomeEvent 触发时,上述辅助程序将被调用,返回的字符串将被记录。

event: SomeEvent was dispatched with values foo=blah, bar=bleh

在我看来,将这些日志辅助程序定义在 MyDomain\DomainEventLoggerHelpers 中是有意义的,因为辅助程序与领域中的事件直接相关。当领域事件更新时,日志辅助程序可以一起更新和提交。