Doctrine Listener versus Subscriber

77

Ich arbeite im Symfony2-Framework und frage mich, wann man einen Doctrine-Abonnenten gegenüber einem Listener verwenden würde. Die Dokumentation von Doctrine für Hörer ist sehr klar, die Abonnenten sind jedoch eher beschönigt. Der Kochbucheintrag von Symfony ist ähnlich.

nurikabe
quelle
Ross Tuck hatte vor einigen Tagen einen Doctrine2-Vortrag auf der DutchPHPConference. Er hat auch die Ereignisse in Doctrine2 behandelt, und seine Folien sind hier: slidehare.net/rosstuck/… vielleicht sind es zusätzliche Informationen / Hilfe für Sie.
Kees Schepers
Sie brauchen wirklich keine Listener in Ihrem eigenen Code. Siehe Niemals Listener verwenden für detailliertere Antworten
Tomáš Votruba

Antworten:

89

Aus meiner Sicht gibt es nur einen großen Unterschied:

  • Der Listener ist angemeldet und gibt die Ereignisse an, die er abhört.
  • Der Abonnent hat eine Methode, die dem Dispatcher mitteilt, welche Ereignisse er abhört

Dies scheint kein großer Unterschied zu sein, aber wenn Sie darüber nachdenken, gibt es einige Fälle, in denen Sie einen über den anderen verwenden möchten:

  • Sie können vielen Dispatchern mit unterschiedlichen Ereignissen einen Listener zuweisen, da diese zum Zeitpunkt der Registrierung festgelegt werden. Sie müssen nur sicherstellen, dass jede Methode im Listener vorhanden ist
  • Sie können die Ereignisse ändern, für die ein Abonnent zur Laufzeit und auch nach der Registrierung des Abonnenten registriert ist, indem Sie den Rückgabewert von ändern. getSubscribedEvents(Denken Sie an eine Zeit, in der Sie ein sehr lautes Ereignis hören und nur einmal etwas ausführen möchten.)

Es könnte andere Unterschiede geben, die mir jedoch nicht bewusst sind!

Sgoettschkes
quelle
19
Kurz gesagt, ein Abonnent ist ein Zuhörer, bei dem die Liste der überwachten Ereignisse veränderlich ist. In getSubscribedEventswürde ich dann ein Array zurückgeben, so etwas wie array(Events::prePersist, Events::postUpdate)ich denke?
Nurikabe
Der Link in @Sgoettschkes Post ist defekt, aktuell sollte Doctrine-project.org/projects/doctrine-orm/en/latest/reference/…
c33s
10

Ich weiß nicht, ob es versehentlich oder absichtlich gemacht wird. Abonnenten haben jedoch eine höhere Priorität als Listener - https://github.com/symfony/symfony/blob/master/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass .php # L73-L98

Von der Doktrin her ist es egal, was es ist (Hörer oder Abonnent), schließlich werden beide als Hörer registriert - https://github.com/doctrine/common/blob/master/lib/Doctrine/Common/EventManager.php # L137-L140

Das habe ich gesehen.

Ruslan Polutsygan
quelle
7

Sie sollten den Ereignisabonnenten verwenden, wenn Sie mehrere Ereignisse in einer Klasse behandeln möchten, z. B. in diesem Artikel auf der symfony2-DokumentseiteMan kann feststellen, dass der Ereignis-Listener nur ein Ereignis verwalten kann. Angenommen, Sie möchten mehrere Ereignisse für eine Entität, prePersist, preUpdate, postPersist usw. verarbeiten. Wenn Sie den Ereignis-Listener verwenden, müssen Sie mehrere Ereignis-Listener codieren. eine für jedes Ereignis, aber wenn Sie mit einem Ereignisabonnenten arbeiten, müssen Sie nur eine Klasse als Ereignis-Abonnenten codieren. Sehen Sie, dass Sie mit dem Ereignisabonnenten mehr als ein Ereignis in einer Klasse verwalten können Um sich auf die Anforderungen des Modellgeschäfts zu konzentrieren, können Sie beispielsweise mehrere Lebenszyklusereignisse global nur für eine Gruppe Ihrer Entitäten behandeln. Dazu können Sie eine übergeordnete Klasse codieren und diese globalen Methoden darin definieren. Lassen Sie dann Ihre Entitäten diese Klasse erben, und später in Ihrem Ereignis-Abonnenten abonnieren Sie jedes gewünschte Ereignis, prePersist,preUpdate, postPersist etc ... und fragen Sie dann nach dieser übergeordneten Klasse und führen Sie diese globalen Methoden aus.

metalvarez
quelle
3
Ich habe Sie vielleicht missverstanden, aber meiner Erfahrung nach kann ein Listener mehrere Ereignisse verwalten, z. B. kann ein Listener Aktionen für prePersist, preUpdate, onFlush usw. definieren.
Chadwick Meyer
@ChadwickMeyer yup i second that 'Dieser Listener kann ein oder mehrere Ereignisse anhören und wird jedes Mal benachrichtigt, wenn diese Ereignisse ausgelöst werden.' direkt aus den Dokumenten
Dheeraj
3

Mit beiden können Sie etwas für ein bestimmtes Ereignis ausführen, bevor / nachdem es fortbesteht usw.

Mit Listenern können Sie jedoch nur Verhaltensweisen ausführen, die in Ihrer Entität gekapselt sind. Ein Beispiel könnte also das Aktualisieren eines Zeitstempels "date_edited" sein.

Wenn Sie sich außerhalb des Kontexts Ihrer Entität bewegen müssen, benötigen Sie einen Abonnenten. Ein gutes Beispiel könnte der Aufruf einer externen API sein oder wenn Sie Daten verwenden / überprüfen müssen, die nicht direkt mit Ihrer Entität zusammenhängen.

Lee Davis
quelle
5
Ich könnte ein Missverständnis haben, aber das klingt nach dem Unterschied zwischen einem Lebenszyklus-Rückruf und einem Ereignis-Listener? Ich versuche festzustellen, wann ich (in Symfony2-Begriffen) a doctrine.event_subscriberim Gegensatz zu verwenden könnte doctrine.event_listener.
Nurikabe
3

Eine weitere wichtige Sache: Mit Doctrine EventSubscribers können Sie keine Priorität festlegen.

Lesen Sie mehr zu diesem Thema hier

Verwelken
quelle
Glühbirne geht an. Vielen Dank!
Nurikabe
2

Hier ist, was der Doc dazu in 4.1 sagt. Da dies global auf Ereignisse angewendet wird, gilt es vermutlich auch für Doctrine (nicht 100% sicher).

Zuhörer oder Abonnenten

Listener und Abonnenten können undeutlich in derselben Anwendung verwendet werden. Die Entscheidung, einen von ihnen zu verwenden, ist normalerweise eine Frage des persönlichen Geschmacks. Es gibt jedoch einige kleinere Vorteile für jeden von ihnen:

  • Abonnenten sind einfacher wiederzuverwenden, da das Wissen über die Ereignisse in der Klasse und nicht in der Service-Definition gespeichert wird. Dies ist der Grund, warum Symfony Abonnenten intern verwendet.
  • Listener sind flexibler, da Bundles sie je nach Konfigurationswert bedingt aktivieren oder deaktivieren können.

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

Kaizoku Gambare
quelle
0

Aus der Dokumentation:

Die häufigste Methode zum Abhören eines Ereignisses besteht darin, einen Ereignis-Listener beim Dispatcher zu registrieren. Dieser Listener kann ein oder mehrere Ereignisse anhören und wird jedes Mal benachrichtigt, wenn diese Ereignisse ausgelöst werden.

Eine andere Möglichkeit, Ereignisse anzuhören, ist über einen Ereignisabonnenten. Ein Ereignisabonnent ist eine PHP-Klasse, die dem Dispatcher genau mitteilen kann, welche Ereignisse er abonnieren soll. Es implementiert die EventSubscriberInterface-Schnittstelle, für die eine einzige statische Methode namens getSubscribeEvents () erforderlich ist.

Siehe das Beispiel hier:

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

Mohammed Yassine CHABLI
quelle