去年,
PHP兼容性概念小组
PHP-FIG发布了几个新规范。 最后一个
PSR-14专门用于事件调度。 像其他PSR一样,这是本地规范,但对标准化的许多方面都有很大影响。
译者的译文:这是一系列出版物的第一部分的翻译,其中PHP-FIG的成员之一拉里(Crell)Garfield解释了PSR-14是什么,它有能力,没有什么以及在其中使用的最佳方法是什么。他们的项目。目的
长期以来,事件分派已在许多语言中使用。 如果您曾经在
Symfony中使用过EventDispatcher,在
Laravel中使用了事件系统,在Drupal中使用了钩子,在Zend框架中使用了
事件管理器 ,
League \ Event软件包,或者类似的东西,那么您就知道这是什么了。
从一般意义上讲,所有这些系统都是“中介观察者”的形式。 一段代码发送一个消息类型为“事件”,中介程序将其发送给其他单独的代码段“侦听器”。 有时信号仅在一个方向上定向,有时“侦听器”可以以某种方式将数据传输回呼叫者。 当然,它们都是不同的并且彼此之间不是很兼容。
对于要连接到各种库和应用程序的独立库,这是一个问题。 通过以一种或另一种形式发送事件,可以扩展许多库,以便其他代码可以联系它们。 但是,实际上,这种中间层是专有的。 然后将运行Symfony EventDispatcher的库与Symfony合并。 然后在其他地方使用它需要安装EventDispatcher并连接到程序中的库。 然后从Drupal
module_invoke_all()
调用绑定系统的库链接到Drupal。 依此类推。
PSR-14的目标是摆脱这种依赖关系的库。 这允许库扩展到薄的公共层,然后方便地将它们转移到另一个环境,而无需付出额外的努力和费用,例如在Symfony,Zend Framework,Laravel,TYPO3,eZ Platform或Slim中。 只要环境与PSR-14兼容,一切都将起作用。
规格书
如前所述,该规范相当轻巧。 这是一种方法中的三个接口,以及有关如何使用它们的元描述。 一切都很简单方便。 以下是这些接口的代码(无注释以节省空间)。
namespace Psr\EventDispatcher; interface EventDispatcherInterface { public function dispatch(object $event); } interface ListenerProviderInterface { public function getListenersForEvent(object $event) : iterable; } interface StoppableEventInterface { public function isPropagationStopped() : bool; }
前两个是规范的核心。
StoppableEventInterface
是我们以后将返回的扩展。
我认为大多数人
EventDispatcher
熟悉
EventDispatcher
它只是您将事件传递给其的方法的对象-您已经在谈论的中介。 但是,事件本身尚未定义-它可以是
任何PHP对象 。 稍后再详细介绍。
大多数现有的实现都有一个充当中介程序或调度程序的对象或一组功能,以及一个用于注册接收事件的代码(侦听器)的位置。 对于PSR-14,我们故意将这两个职责划分为不同的对象。 调度程序从构成此列表的提供程序对象中接收侦听器列表。
提供者从哪里获取侦听器列表? 是的,他要去哪里! 连接侦听器和事件有十亿种方法,它们都是绝对有效且不兼容的。 一开始,我们认为注册学生的“唯一途径”的标准化会太有限。 但是,通过标准化将侦听器连接到调度程序的过程,您可以得到出色的灵活性,而不必强迫用户执行一些奇怪而难以理解的事情。
另外,该代码未指示侦听器是什么。 它可以是任何能够感知信号的PHP片段:一个函数,一个匿名函数,一个对象方法,任何东西。 由于被调用的对象可以执行任何操作,因此可以将匿名函数作为侦听器用作侦听器,该匿名函数从DI容器中延迟加载服务并调用服务中的方法,该方法实际上包含侦听代码。
简而言之,调度程序是图书馆作者的一种简单易用的API。 侦听器提供程序为框架集成商提供了健壮且灵活的API,而调度程序和提供程序之间的关系将它们整合在一起。
简单的例子
一般而言,将所有部分组合为一个整体的方案看起来像这样。
class Dispatcher implements EventDispatcherInterface { public function __construct(ListenerProviderInterface $provider) { $this->provider = $provider; } public function dispatch(object $event) { foreach ($this->provider->getListenersForEvent($event) as $listener) { $listener($event); } return $event; } } $dispatcher = new Dispatcher($provider); $event = new SomethingHappened(); $dispatcher->dispatch($event);
这小段代码提供了很多机会,而且非常灵活。 在以下文章中,我们将详细讨论其属性,分析一些结构解决方案,并考虑使用此类轻量级事件的多种方法。
代号
主要框架和应用程序已支持PSR-14。
- Matthew Weier O'Phinney已承诺在Zend框架的zend-eventmanager 4.0中引入对PSR-14的支持。
- Symfony 最近宣布对EventDispatcher进行更改,以与PSR-14兼容,它将在5.0 / 5.1中提供全面支持。
- Yii框架宣布打算将PSR-14集成到3.0版中 。
- TYPO3 CMS的Benni Mack说,在下一个TYPO3版本中,所有现有的陷阱+信号/插槽概念都将支持PSR-14。
PSR-14还具有三个可以在任何应用程序中使用的功能完全独立的实现。
- 本文作者Larry Garfield的Tukio 。
- Matthew Weier O'Phinney的Phly事件调度程序。
- Benni Mack的Kart ,它是嵌入式插件。
作者感谢整个PSR工作组:
拉里·加菲尔德 ,
塞斯·简·基维特 ,
本杰明·麦克 ,
伊丽莎白·史密斯 ,
瑞安·韦弗 ,
马修·维尔·奥芬妮 。 在整个工作过程中,该过程非常富有成效:每个人都应该按照集体意愿一起工作。 结果令人愉悦,我希望在架构方面的联合工作中所做的所有进一步努力都能够取得成果。
您可以从下一部分的原始内容和文档中找到更多详细信息,也可以从5月17日在PHP Russia找到更多详细信息。 第二种选择具有吸引力,原因有几个。 例如,计划委员会负责人Alexander( samdark )Makarov是在Yii推出PSR-14的人之一。 原则上,程序委员会和发言人的组成非常强大,在PHP的专业使用领域,几乎没有任何话题可以在本次会议上讨论。