lubobill1990/event-dispatcher

dev-master / 3.0.x-dev 2020-08-24 17:02 UTC

This package is auto-updated.

Last update: 2024-08-25 02:08:47 UTC


README

Yii 事件调度器


符合PSR-14的事件调度器提供了分发事件和监听分发事件的特性。

Latest Stable Version Total Downloads Build Status Code Coverage Scrutinizer Code Quality Mutation testing badge static analysis

特性

  • 符合PSR-14
  • 简单轻量
  • 鼓励设计事件层次结构
  • 可以组合多个事件监听提供者

通用用法

该库由两部分组成:事件调度器和事件监听提供者。提供者的任务是为特定事件类型注册监听器。调度器的任务是获取一个事件,从提供者那里获取该事件的监听器,并按顺序调用它们。

// add some listeners
$listeners = (new \Yiisoft\EventDispatcher\Provider\ListenerCollection())
    ->add(function (AfterDocumentProcessed $event) {
        $document = $event->getDocument();
        // do something with document
    });

$provider = new Yiisoft\EventDispatcher\Provider\Provider($listeners);
$dispatcher = new Yiisoft\EventDispatcher\Dispatcher\Dispatcher($provider);

事件分发可能看起来像

class DocumentProcessor
{
    public function process(Document $document)
    {
        // process the document
        $dispatcher->dispatch(new AfterDocumentProcessed($document));
    }
}

可停止的事件

通过实现Psr\EventDispatcher\StoppableEventInterface,可以将事件设置为可停止的

class BusyEvent implements Psr\EventDispatcher\StoppableEventInterface
{
    // ...

    public function isPropagationStopped(): bool
    {
        return true;
    }
}

这样我们就可以确保只有第一个事件监听器能够处理事件。另一种选择是允许在某个监听器中提供相应的事件方法来停止传播。

事件层次结构

出于故意,事件没有名称或通配符匹配。可以使用事件类名称和类/接口层次结构以及组合来实现很大的灵活性

interface DocumentEvent
{
}

class BeforeDocumentProcessed implements DocumentEvent
{
}

class AfterDocumentProcessed implements DocumentEvent
{
}

使用上述接口,可以监听所有与文档相关的事件

$listeners->add(function (DocumentEvent $event) {
    // log events here
});

组合多个监听提供者

如果您想组合多个监听提供者,可以使用CompositeProvider

$compositeProvider = new Yiisoft\EventDispatcher\Provider\CompositeProvider();
$provider = new Yiisoft\EventDispatcher\Provider\Provider();
$compositeProvider->add($provider);
$compositeProvider->add(new class implements ListenerProviderInterface {
    public function getListenersForEvent(object $event): iterable
    {
        yield function ($event) {
            // handle 
        };
    }
});

$dispatcher = new Yiisoft\EventDispatcher\Dispatcher\Dispatcher($compositeProvider);

使用具体事件名称注册监听器

您可以使用更简单的监听提供者,允许您指定它们可以提供哪些事件。

在某些特定情况下可能很有用,例如,如果其中一个监听器不需要传递事件对象作为参数(如果监听器只需要在运行时特定阶段运行,但不需要事件数据)。

在这种情况下,如果您需要包含在此库中的两个提供者的功能,建议使用聚合(参见上面)。

$listeners = (new \Yiisoft\EventDispatcher\Provider\ListenerCollection())
    ->add(static function () {
    // this function does not need an event object as argument
}, SomeEvent::class);

单元测试

该包使用PHPUnit进行测试。要运行测试

./vendor/bin/phpunit

突变测试

该包的测试使用Infection突变框架进行检查。要运行它

./vendor/bin/infection

静态分析

使用Phan对代码进行静态分析。要运行静态分析

./vendor/bin/phan

致谢

  • Larry Garfield (@crell) 对可调用参数类型的初始实现表示感谢。