silverstripe / event-dispatcher
在Silverstripe CMS或您的Silverstripe应用程序中发布和订阅事件
Requires
- php: ^8.1
- psr/event-dispatcher: ^1
- silverstripe/framework: ^5
- symfony/event-dispatcher: ^6.1
Requires (Dev)
- phpunit/phpunit: ^9.5
- squizlabs/php_codesniffer: ^3.7
README
本模块为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 $eventName
和EventContextInterface $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模块。
请直接向模块维护者报告安全问题。请勿在问题跟踪器中提交安全问题。
开发和贡献
如果您想为此模块做出贡献,请确保您提交了拉取请求并与模块维护者进行讨论。