EventDispatcher组件
EventDispatcher组件¶
EventDispatcher组件提供了一些工具,这些工具允许应用程序组件通过分派事件和监听事件来相互通信。
介绍¶
面向对象的代码已经有很长的路要能确保代码可扩展性。通过创建具有明确定义责任的类,您的代码变得更灵活,开发人员可以使用子类扩展它们来修改其行为。但是,如果他们想与其他开发人员分享那些也完成自己的子类的其他开发人员,则代码继承不再是答案。
考虑您想要为项目提供插件系统的真实界面。插件应该能够添加方法,或者在执行方法之前或之后做某事,而不会干扰其他插件。通过单一继承解决,这不是一个简单的问题,即使使用PHP可能进行多种继承,它也会附带自己的缺点。
Symfob娱乐下载ony EventDispatcher组件实现了介质和观察者设计模式,使所有这些事情成为可能,并使您的项目真正可扩展。
举例httpkernel组件。一旦响应
已经创建了对象,允许系统中的其他元素修改它可能是有用的(例如,在其实际使用之前添加一些缓存报头)。为了使这一点成为可能,Symfony Kernel抛出ob娱乐下载了一个事件 -kernel.response
。这是它的工作原理:
- 一种听众(PHP对象)讲述一个中心调度员对象,它希望侦听
kernel.response
事件; - 在某些时候,Symfony Kerneob娱乐下载l告诉了调度员派遣的对象
kernel.response
事件,通过它事件
可以访问的对象响应
目的; - 调度员通知(即呼叫方法)所有侦听器
kernel.response
事件,允许他们中的每一个对其进行修改响应
目的。
安装¶
1 |
$Composer需要Symfonyob娱乐下载 / Event-Dispatcher
|
笔记
如果在Symfony应用程序之外安装此组件,则必须要求ob娱乐下载供应商/ autoload.php.
代码中的文件以启用Composer提供的类自动加载机制。读本文更多细节。
用法¶
也可以看看
本文介绍了如何在任何PHP应用程序中使用EventDispatcher功能作为独立组件。阅读活动和活动听众文章了解如何在Symfony应用程序中使用它。ob娱乐下载
活动¶
当派出事件时,它通过唯一名称标识(例如,kernel.response
),任何数量的听众可能正在倾听。一个ob娱乐下载Symfony \ Contracts \ EventDispatcher \ Event
实例也被创建并传递给所有侦听器。因为你稍后会看到的事件
对象本身通常包含正在调度的事件的数据。
命名惯例¶
唯一的事件名可以是任何字符串,但可以遵循一些命名约定:
- 仅使用小写字母,数字,点(
。
)和下划线(_
); - 前缀名称后跟一个点(例如。
命令。*
那用户。*
); - 具有动词的终端名称,表示已经采取了哪些操作(例如
订单已下
)。
分配器¶
调度程序是事件调度程序系统的核心对象。通常,创建单个调度程序,该调度程序维护侦听器的注册表。当通过调度程序调度事件时,它会通知所有侦听器在该事件中注册:
用ob娱乐下载symfony \ component \ enceDispatcher \ enceDispatcher;$调度员=新的EventDispatcher.();
连接听众¶
为了利用现有事件,您需要将侦听器连接到调度程序,以便在发送事件时可以通知它。对Dispatcher的调用AddListener()
方法将任何有效的PHP可调用对象关联到一个事件:
$倾听者=新的Acmelistener.();$调度员- >addListener.('acme.foo.action'那[$倾听者那'onfooaction']);
这AddListener()
方法最多需要三个参数:
- 这个侦听器想要收听的事件名称(字符串);
- 在调度指定的事件时将执行的PHP可调用;
- 可选的优先级,定义为正或负整数(默认为
0.
)。数量越高,侦听器的较早。如果两个侦听器具有相同的优先级,则按向调度程序添加到调度程序的顺序执行它们。
笔记
一种PHP可谴责是一个可以用的php变量call_user_func()
功能和返回真的
当传递到is_callable()
函数。它可以是\关闭
实例,实现一个对象__invoke()
方法(这是闭包的事实上),表示表示对象方法或类方法的函数或数组的字符串。
到目前为止,您已经看到了PHP对象如何注册为侦听器。您还可以注册PHP关闭作为活动听众:
用ob娱乐下载Symfony \ Contracts \ EventDispatcher \ Event;$调度员- >addListener.('acme.foo.action'那功能(事件$赛事){//将在派遣acme.foo.action事件时执行});
侦听器在Dispatcher注册后,它会等待在通知事件之前。在上面的例子中,当Acme.foo.action.
派遣派遣,调度员呼叫Acmelistener :: onfooaction()
方法并通过事件
对象作为单个参数:
用ob娱乐下载Symfony \ Contracts \ EventDispatcher \ Event;班级Acmelistener.{/ /……公共功能onfooaction.(事件$赛事){/ /……做某事}}
这$赛事
参数是在调度事件时传递的事件对象。在许多情况下,使用额外信息传递特殊事件子类。您可以检查每个事件的文档或实现以确定欧宝官网下载app传递了哪些实例。
创建和调度活动¶
除了用现有事件注册监听器之外,您还可以创建和分派自己的事件。这在创建第三方库时很有用,在您希望保持自己系统的不同组件的灵活性和解耦性时也很有用。
创建一个事件类¶
假设您想创建一个新事件 -订单已下
- 每次客户订购产品时都会调度。调度此事件时,您将通过可访问已放置订单的自定义事件实例。首先创建此自定义事件类并记录它:
名称空间acme \ store \活动;用Acme \ Store \订单;用ob娱乐下载Symfony \ Contracts \ EventDispatcher \ Event;/ ***每次创建订单时都会调度Order.Placed事件*在系统中。* /班级OrderPlacedEvent.延伸事件{公共const名称='订单已下';保护$订单;公共功能__构造(命令$订单){$这一点- >命令=$订单;}公共功能getOrder.():命令{返回$这一点- >命令;}}
每个侦听器现在都通过通过该侦听器访问订单getOrder()
方法。
笔记
如果您不需要将任何其他数据传递给事件侦听器,您也可以使用默认值ob娱乐下载Symfony \ Contracts \ EventDispatcher \ Event
班级。在这种情况下,您可以在通用中记录事件及其名称储藏商
类,类似于ob娱乐下载symfony \ component \ httpkernel \ kernelevents
班级。
派遣事件¶
这派遣()
方法通知给定事件的所有侦听器。需要两个论点:事件
实例传递给该事件的每个监听器和要分派的事件的名称:
用Acme \ Store \ Event \ OrderPlacedEvent;用Acme \ Store \订单;//订单是以某种方式创建或检索$订单=新的命令();/ /……//创建OrderplacedEvent并调度它$赛事=新的OrderPlacedEvent.($订单);$调度员- >派遣($赛事那OrderPlacedEvent.::名称);
请注意特别的OrderPlacedEvent.
对象是创建并传递给的派遣()
方法。现在,任何倾听者订单已下
活动将收到OrderPlacedEvent.
。
使用活动订阅者¶
倾听事件的最常见方法是注册一个活动侦听器随时随地。此侦听器可以收听一个或多个事件,每次调度这些事件时都会通知。
通过一个倾听事件的另一种方法是通过活动订阅者。事件订户是一个能够准确地告诉调度程序所订阅的事件的PHP类。它实现了这一点ob娱乐下载symfony \ component \ enceDispatcher \ eventsubscriberInterface
接口,需要一个静态方法调用getSubscribedEvents()
。采取订阅者的以下示例kernel.response
和订单已下
活动:
名称空间acme \ store \活动;用Acme \ Store \ Event \ OrderPlacedEvent;用ob娱乐下载symfony \ component \ enceDispatcher \ eventsubscriberInterface;用ob娱乐下载symfony \ component \ httpkernel \事件\ responseavent;用ob娱乐下载symfony \ component \ httpkernel \ kernelevents;班级Storesubscriber.实施eventsubscriberInterface.{公共静止的功能getsubscribedEvents.(){返回[内科特::回复=>[['onkernelresponsepre'那10.],['onkernelresponsepost'那-10.],],OrderPlacedEvent.::名称=>“onStoreOrder”那];}公共功能onkernelresponsepte.(响应$赛事){/ /……}公共功能onkernelresponsepost.(响应$赛事){/ /……}公共功能在storeorder.(OrderPlacedEvent.$赛事){/ /……}}
这与侦听器类非常相似,除了类本身可以告诉调度程序它应该收听的事件。要使用调度程序注册用户,请使用addsubscriber()
方法:
用Acme \ Store \ Event \ StoreBscriber;/ /……$用户=新的Storesubscriber.();$调度员- >addsubscriber.($用户);
调度员将自动注册订户的每项事件getSubscribedEvents()
方法。此方法返回由事件名称索引的数组,其值是调用的方法名称或由呼叫的方法名称组成的数组(默认为的正面或负整数)0.
)。
上面的示例显示了如何在订阅者中为同一事件注册多个侦听器方法,也显示如何传递每个侦听器方法的优先级。数量越高,方法的越早调用。在上面的例子中,当kernel.response
事件被触发,方法onkernelresponsepre()
和onkernelresponsepost()
按此顺序调用。
停止事件流/传播¶
在某些情况下,听众可能对阻止任何其他侦听器称为调用的意义。换句话说,侦听器需要能够告诉调度器将事件的所有传播停止到未来的侦听器(即不通知任何侦听器)。这可以通过收听者内部通过stopprojagation()
方法:
用Acme \ Store \ Event \ OrderPlacedEvent;公共功能在storeorder.(OrderPlacedEvent.$赛事){/ /……$赛事- >stopPropagation();}
现在,任何听众订单已下
尚未被称为意志不是叫做。
可以通过使用该事件来检测事件是否已停止ispropagationstopped()
返回布尔值的方法:
/ /……$调度员- >派遣($赛事那'foo.event');如果($赛事- >ispropagationstopped()){/ /……}
EventDispatcher意识到事件和侦听器¶
这EventDispatcher.
始终通过调度事件,事件的名称和对侦听器的引用。这可以导致一些高级应用EventDispatcher.
包括调度侦听器中的其他事件,链接事件甚至延迟将侦听器甚至进入Dispatcher对象。
事件名称内省¶
这EventDispatcher.
实例,以及已调度的事件的名称,作为侦听器的参数传递:
用ob娱乐下载Symfony \ Contracts \ EventDispatcher \ Event;用ob娱乐下载symfony \ contracts \ enceDispatcher \ enceDispatcherInterface;班级Foo{公共功能MyeventListener.(事件$赛事那$ eventName.那EventDispatcherInterface.$调度员){// ...用事件名称做点什么}}
这项工作包括代码样本,是在a下获得的许可Creative Commons by-SA 3.0执照。