silverstripe/event-dispatcher

在Silverstripe CMS或您的Silverstripe应用程序中发布和订阅事件

安装次数: 719,363

依赖项: 3

建议者: 0

安全: 0

星标: 5

关注者: 11

分支: 2

公开问题: 2

类型:silverstripe-vendormodule

1.0.1 2024-06-17 00:39 UTC

This package is auto-updated.

Last update: 2024-09-18 03:30:51 UTC


README

CI

本模块为Silverstripe CMS应用程序提供PSR-14事件调度器。它通过如onAfterWrite之类的钩子,用于实现替代传统命令式设计的响应式编程范式。

大部分底层工作由Symfony的EventDispatcher处理,但可以通过依赖注入来替换。

要求

  • silverstripe/framework: ^4.5

安装

$ composer require silverstripe/event-dispatcher

使用

API有三个主要组件

  • Dispatcher负责注册事件监听器和触发事件
  • Listeners是触发事件的类,通常通过扩展钩子实现
  • Handlers是执行响应事件的代码的类。

触发事件

use SilverStripe\EventDispatcher\Dispatch\Dispatcher;
use SilverStripe\EventDispatcher\Symfony\Event;

Dispatcher::singleton()->trigger('createOrder', Event::create(
    null,
    [
        'id' => $order->ID,
        'paymentMethod' => $order->PaymentMethod
    ]
));

trigger函数接受两个参数:string $eventNameEventContextInterface $context。该$context对象可以将任意数据传递给任何订阅该事件的处理程序。

事件处理

事件处理程序必须实现EventHandlerInterface,该接口要求一个fire()方法。

use SilverStripe\EventDispatcher\Dispatch\EventHandlerInterface;
use SilverStripe\EventDispatcher\Event\EventContextInterface;

class OrderHandler implements EventHandlerInterface
{
    public function fire(EventContextInterface $context): void
    {
        $orderID = $context->get('id');
        $paymentMethod = $context->get('paymentMethod');
        // Do something in response to the order being created
    }
}

订阅事件

将事件处理程序与调度器注册的最佳方式是通过配置。

SilverStripe\Core\Injector\Injector:
  SilverStripe\EventDispatcher\Dispatch\Dispatcher:
    properties:
      handlers:
        # Arbitrary key. Allows other config to override.
        orders:
          on: [ orderCreated ]
          handler: %$MyProject\MyOrderHandler

取消订阅事件

要删除事件处理程序,使用带有off节点的配置覆盖。

SilverStripe\Core\Injector\Injector:
  SilverStripe\EventDispatcher\Dispatch\Dispatcher:
    properties:
      handlers:
        orders:
          off: [ orderCreated ]

以过程化方式管理事件

要直接与Dispatcher实例交互,请使用DispatcherLoaderInterface

use SilverStripe\EventDispatcher\Dispatch\DispatcherLoaderInterface;
use SilverStripe\EventDispatcher\Dispatch\EventDispatcherInterface;

class MyLoader implements DispatcherLoaderInterface
{
    public function addToDispatcher(EventDispatcherInterface $dispatcher) : void
    {
        $dispatcher->addListener('myEvent', $myHandler);
        $dispatcher->removeListener('anotherEvent', $anotherHandler);
    }
}

然后,在Injector中注册加载器。

SilverStripe\Core\Injector\Injector:
  SilverStripe\EventDispatcher\Dispatch\Dispatcher:
    properties:
      loaders:
        myLoader: %$MyProject\MyLoader

操作标识符和上下文

每个处理程序都传递一个上下文对象,该对象公开一个操作标识符。这是一个字符串,提供了处理程序可以在其实现中使用的事件发生时的具体信息。例如,如果您想为表单提交编写事件处理程序,其中一些处理程序适用于所有表单提交,而其他处理程序适用于特定表单,您可以在您的EventContext对象中传递表单名称作为操作标识符。

use SilverStripe\EventDispatcher\Dispatch\Dispatcher;
use SilverStripe\EventDispatcher\Symfony\Event;

Dispatcher::singleton()->trigger('formSubmitted', Event::create(
    'contact',
    [
        'name' => $formData['Name'],
        // etc..
    ]
));

事件总是以eventName.<action identifier>的形式调用。例如 formSubmitted.contact,允许订阅者仅对特定子集的事件做出反应。

SilverStripe\Core\Injector\Injector:
  SilverStripe\EventDispatcher\Dispatch\Dispatcher:
    properties:
      handlers:
        forms:
          # handler for all form submissions
          on: [ formSubmitted ]
          handler: %$MyProject\MyFormHandler
        contactForm:
          # handler for all a specific form
          on: [ formSubmitted.contact ]
          handler: %$MyProject\MyContactHandler

在这种情况下,一个联系表单提交将触发两个处理程序,按照特定性顺序(formSubmitted.contact首先)。

如何找到您的操作标识符

调试事件的最简单方法是放置断点或将日志记录到Dispatcher::trigger()函数中。这将提供有关何时触发哪些事件以及上下文的详细信息。

public function trigger(string $event, EventContextInterface $context): void
{
    error_log($event);
    error_log($context->getAction());
    // ...

当日志设置到位时,您只需转到CMS并执行您感兴趣的操作。这应该将标识符列表缩小到更小的子集。

事件上下文

在上面的示例中,联系表单数据作为上下文传递给Event对象。

use SilverStripe\EventDispatcher\Dispatch\Dispatcher;
use SilverStripe\EventDispatcher\Symfony\Event;

Dispatcher::singleton()->trigger('formSubmitted', Event::create(
    'contact',
    [
        'name' => $formData['Name'],
        // etc..
    ]
));

在处理程序中,可以使用get(string $property)方法访问它。

public function fire(EventContextInterface $context): void
{
    $name = $context->get('Name');
    // do more stuff...
}

请注意,get方法可以优雅地失败,并在属性不存在时返回null

许可

参见许可证

问题跟踪器

问题在此存储库的问题部分进行跟踪。在提交问题之前,请阅读现有问题以确保您的问题是唯一的。

如果问题看起来像是新的错误

  • 创建一个新的问题
  • 描述重现您的问题所需的步骤以及预期的结果。单元测试、截图和屏幕录制在这里可能会有所帮助。
  • 尽可能详细地描述您的环境:Silverstripe版本、浏览器、PHP版本、操作系统、任何已安装的Silverstripe模块。

请直接向模块维护者报告安全问题。请勿在问题跟踪器中提交安全问题。

开发和贡献

如果您想为此模块做出贡献,请确保您提交了拉取请求并与模块维护者进行讨论。