Doctrine Listener与Subscriber

时间:2012-05-24 02:32:02

标签: symfony doctrine-orm

我正在使用Symfony2框架,并想知道何时使用Doctrine订阅者而不是侦听器。对于听众而言,Doctrine的documentation非常清楚,但订阅者却被掩盖了。 Symfony的cookbook entry类似。

7 个答案:

答案 0 :(得分:84)

从我的观点来看,只有一个主要区别:

  • 监听器已注册,指定它侦听的事件。
  • 订阅者有一种方法告诉调度员它正在侦听哪些事件

这可能看起来不是很大的区别,但是如果你考虑一下,有些情况下你想要使用一个而不是另一个:

  • 您可以为具有不同事件的多个调度程序分配一个侦听器,因为它们是在注册时设置的。您只需确保侦听器中的每个方法都已到位
  • 您可以在运行时更改订阅者注册的事件,甚至可以在更改getSubscribedEvents的返回值后注册订阅者(想想您收听非常嘈杂的事件的时间,并且您只想执行一次)

虽然可能还有其他我不知道的差异!

答案 1 :(得分:8)

不知道是不是意外地或故意地完成了......但是订阅者更倾向于听众 - 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

这是我发现的。

答案 2 :(得分:7)

当你想要在一个类中处理多个事件时,你应该使用事件订阅者,例如在这个symfony2 doc page article中,可能会注意到事件监听器只能管理一个事件,但是假设你想要处理一个实体,prePersist,preUpdate,postPersist等的几个事件...如果你使用事件监听器,你必须编写几个事件监听器,每个事件一个,但如果你去事件用户,你只需要编写一个类事件susbcriber,看看使用事件订阅者,您可以在一个类中管理多个事件,这就是我使用它的方式,我更倾向于专注于模型业务需要的代码,这可能是你想要处理的一个例子几个生命周期事件全局只针对一组实体,为此你可以编写父类并在其中定义那些全局方法,然后让你的实体继承该类,然后在你的事件中让你订阅你想要的每个事件,prePersist ,preUpdate,postPersist等... a然后,请求该父类并执行这些全局方法。

答案 3 :(得分:3)

两者都允许你在事件前/后持续等特定事件上执行某些事情。

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

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

答案 4 :(得分:3)

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

详细了解此问题here

答案 5 :(得分:2)

以下是文档在4.1中对此的说法。 由于这是全局应用于事件,我认为它也适用于Doctrine(不是100%肯定)。

  

听众或订阅者

     

监听器和订阅者可以在同一个应用程序中模糊地使用。决定使用它们中的任何一个通常都是一个问题   个人品味。但是,每个都有一些小优点   他们:

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

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

答案 6 :(得分:0)

从文档中:

  

收听事件的最常见方法是注册事件   与调度程序的侦听器。此听众可以听一个或多个   事件,并在每次事件分派时得到通知。

     

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

在此处查看示例:

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