侦听器与订户


77

我正在使用Symfony2框架,想知道何时使用Doctrine订户而不是侦听器。对于听众,Doctrine的文档非常清晰,但是订阅者却被蒙蔽了。Symfony的食谱条目与此类似。


几天前,Ross Tuck在DutchPHPConference上进行了Doctrine2演讲。他还处理了Doctrine2中的事件,他的幻灯片在这里:slideshare.net/rosstuck / ...也许对您有一些额外的信息/帮助。
Kees Schepers 2012年

您确实不需要自己的代码中的侦听器。见永远不要使用监听器的更详细的解答
托马什Votruba

Answers:


89

在我看来,只有一个主要区别:

  • 侦听器已注册,指定了侦听事件。
  • 订阅服务器有一种方法可以告诉调度程序正在侦听哪些事件

这看起来似乎没有太大的区别,但是如果您考虑一下,在某些情况下,您可能会希望使用其中一种:

  • 您可以将一个侦听器分配给具有不同事件的许多调度程序,因为它们是在注册时设置的。您只需要确保侦听器中的每个方法都到位
  • 您可以通过更改以下内容的返回值来更改运行时甚至在注册订户后注册的事件getSubscribedEvents:(考虑一下您听到一个非常嘈杂的事件并且只想执行一次的事件)

我可能还没有意识到其他差异!


19
因此,简而言之,订户是侦听器,其中受监视事件的列表是可变的?在getSubscribedEvents我会再返回一个数组,像array(Events::prePersist, Events::postUpdate)我猜?
nurikabe 2012年


@Sgoettschkes帖子中的链接已断开,当前应为doctrine-project.org/projects/doctrine-orm/en/latest/reference/…–
c33s

10

不知道它是偶然还是有意完成。但是订户比侦听器具有更高的优先级-https: //github.com/symfony/symfony/blob/master/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass .php#L73-L98

从学说的角度讲,它不在乎它是什么(侦听器或订户),最终两者都注册为侦听器-https: //github.com/doctrine/common/blob/master/lib/Doctrine/Common/EventManager.php #L137-L140

这就是我发现的。


7

如果要在一个类中处理多个事件,则应使用事件订阅程序,例如,在此symfony2文档页面文章中,您可能会注意到事件监听器只能管理一个事件,但是假设您要处理一个实体的多个事件,例如prePersist,preUpdate,postPersist等...如果您使用事件监听器,则必须编写多个事件监听器,每个事件一个,但是如果您与事件订阅者一起使用,则只需要为事件订阅者编写一个类,就可以看到事件订阅者可以在一个类中管理多个事件,这就是我的使用方式,我认为为了专注于模型业务需要的代码,您可能想只为一组实体全局处理多个生命周期事件,为此,您可以编写父类并在其中定义这些全局方法,然后让您的实体继承该类,然后在事件订阅者中订阅您想要的每个事件,prePersist,preUpdate,postPersist等...,然后请求该父类并执行那些全局方法。


3
我可能误会了您,但是以我的经验,一个侦听器可以管理多个事件,例如,一个侦听器可以为prePersist,preUpdate,onFlush等定义操作。–
Chadwick Meyer

@ChadwickMeyer是的,我同意“此侦听器可以侦听一个或多个事件,并在每次调度这些事件时收到通知。” 直接来自文档
Dheeraj

3

两者都允许您在持久之前/之后的特定事件上执行某些操作。

但是,侦听器仅允许您执行封装在实体中的行为。因此,一个示例可能是更新“ date_edited”时间戳。

如果您需要移出实体的上下文,则需要一个订阅者。一个很好的例子可能是调用外部API,或者如果您需要使用/检查与您的实体不直接相关的数据。


5
我可能会误会,但这听起来像生命周期回调和事件侦听器之间的区别?我试图确定何时可以使用(以Symfony2的术语)a doctrine.event_subscriber而不是doctrine.event_listener
nurikabe 2012年

3

另一个重要的事情是:Doctrine EventSubscribers不允许您设置优先级。

此处阅读有关此问题的更多信息


灯泡亮了。谢谢!
nurikabe

2

这就是文档在4.1中所说的。因为这是全局性地应用于事件,所以我认为它也适用于“教义”(并非100%肯定)。

侦听器或订户

侦听器和订阅者可以在同一应用程序中模糊地使用。选择使用其中之一通常取决于个人喜好。但是,它们每个都有一些次要的优点:

  • 订户更易于重用,因为事件的知识保存在类中,而不是服务定义中。这就是Symfony内部使用订户的原因。
  • 侦听器更加灵活,因为捆绑包可以根据某些配置值有条件地启用或禁用它们。

http://symfony.com/doc/master/event_dispatcher.html#listeners-or-subscribers


0

从文档中:

侦听事件的最常见方法是在调度程序中注册事件侦听器。该侦听器可以侦听一个或多个事件,并在每次调度这些事件时收到通知。

监听事件的另一种方法是通过事件订阅者。事件订阅者是一个PHP类,它能够准确告知调度程序应订阅的事件。它实现了EventSubscriberInterface接口,该接口需要一个名为getSubscribedEvents()的静态方法。

在这里查看示例:

https://symfony.com/doc/3.3/components/event_dispatcher.html

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.