yiisoft/event-dispatcher

Yii 事件分发器

1.1.0 2022-10-27 12:02 UTC

This package is auto-updated.

Last update: 2024-09-17 08:30:22 UTC


README

Yii

Yii 事件分发器


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

兼容 PSR-14 的事件分发器提供分发事件和监听分发事件的能力。

功能

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

要求

  • PHP 8.0 或更高版本。

安装

可以使用 Composer 安装此包。

composer require yiisoft/event-dispatcher

通用用法

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

// 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);

事件分发可能如下所示

use Psr\EventDispatcher\EventDispatcherInterface;

final class DocumentProcessor
{
    private EventDispatcherInterface $eventDispatcher;
    
    public function __construct(EventDispatcherInterface $eventDispatcher) {
        $this->eventDispatcher = $eventDispatcher;
    }

    public function process(Document $document): void
    {
        // Process the document, then dispatch completion event.
        $this->eventDispatcher->dispatch(new AfterDocumentProcessed($document));
    }
}

可停止的事件

可以通过实现 Psr\EventDispatcher\StoppableEventInterface 使事件可停止。

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

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

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

事件层次结构

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

interface DocumentEvent
{
}

final class BeforeDocumentProcessed implements DocumentEvent
{
}

final class AfterDocumentProcessed implements DocumentEvent
{
}

使用上述接口监听所有文档相关事件可以这样进行

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

组合多个监听提供者

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

$compositeProvider = new Yiisoft\EventDispatcher\Provider\CompositeProvider();
$provider = new Yiisoft\EventDispatcher\Provider\Provider($listeners);
$compositeProvider->add($provider);
$compositeProvider->add(new class implements ListenerProviderInterface {
    public function getListenersForEvent(object $event): iterable
    {
        yield static 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);

分发到多个分发器

可能需要同时通过多个分发器分发事件。这可以像以下这样做

use Yiisoft\EventDispatcher\Dispatcher\CompositeDispatcher;
use Yiisoft\EventDispatcher\Dispatcher\Dispatcher;
use Yiisoft\EventDispatcher\Provider\ListenerCollection;
use Yiisoft\EventDispatcher\Provider\Provider;

// Add some listeners.
$listeners1 = (new ListenerCollection())
    ->add(function (AfterDocumentProcessed $event) {
        $document = $event->getDocument();
        // Do something with document.
    });

$provider1 = new Provider($listeners1);

// Add some listeners.
$listeners2 = (new ListenerCollection())
    ->add(function (AfterDocumentProcessed $event) {
        $document = $event->getDocument();
        // Do something with document.
    });

$provider2 = new Provider($listeners2);


$dispatcher = new CompositeDispatcher();
$dispatcher->attach(new Dispatcher($provider1));
$dispatcher->attach(new Dispatcher($provider2));

$dispatcher->dispatch(new MyEvent());

文档

如果您需要帮助或有疑问,Yii 论坛 是一个好地方。您还可以查看其他 Yii 社区资源

许可

Yii 事件分发器是免费软件。它在 BSD 许可证条款下发布。有关更多信息,请参阅 LICENSE

Yii 软件 维护。

致谢

  • Larry Garfield (@crell) 为可调用参数类型的推导提供初始实现。

支持此项目

Open Collective

关注更新

Official website Twitter Telegram Facebook Slack