Symfony DI: Zirkuläre Service-Referenz mit Doctrine-Ereignis-Abonnenten

8

Um den Code über die Ticketbenachrichtigungssysteme zu überarbeiten, habe ich einen Doctrine-Listener erstellt:

%Vor%

Das Ziel besteht darin, Benachrichtigungen zu versenden, wenn ein Ticket oder eine TicketMessage-Entität über Mail, Slack und interne Benachrichtigungen mit Doctrine SQL erstellt oder aktualisiert wird.

Ich hatte bereits ein zirkuläres Abhängigkeitsproblem mit Doctrine, also habe ich den Entity Manager stattdessen aus den Event-Args eingefügt:

%Vor%

Der Manager wird vom TicketNotificationListener

injiziert %Vor%

Die Webanwendung funktioniert, aber wenn ich versuche, einen Befehl wie doctrine:database:drop auszuführen, habe ich Folgendes:

%Vor%

Aber das betrifft die Anbieterdienste.

Wie löst man das? Warum habe ich diesen Fehler nur bei cli?

Danke.

    
Soullivaneuh 29.09.2016, 12:00
quelle

2 Antworten

4

IMHO mischt ihr hier zwei verschiedene Konzepte:

  • Domain Events ( TicketWasClosed zum Beispiel)
  • Doctrine Lebenszyklus-Ereignisse ( PostPersist zum Beispiel)

Das Ereignissystem von Doctrine soll sich in den Persistenzfluss einklinken, um Dinge zu behandeln, die direkt mit dem Speichern und Laden aus der Datenbank zusammenhängen. Es sollte für nichts anderes verwendet werden.

Für mich sieht es so aus, als ob Sie vorgehen wollen:

  

Wenn ein Ticket geschlossen wurde, senden Sie eine Benachrichtigung.

Das hat nichts mit Doktrin oder Persistenz im Allgemeinen zu tun. Was Sie brauchen, ist ein anderes Ereignissystem für Domain-Ereignisse.

Sie können weiterhin den EventManager von Doctrine verwenden. Stellen Sie jedoch sicher, dass Sie eine zweite Instanz erstellen, die Sie für Domain-Ereignisse verwenden.

Sie können auch etwas anderes verwenden. Symfonys EventDispatcher zum Beispiel. Wenn Sie das Symfony-Framework verwenden, gilt dasselbe auch hier: Verwenden Sie keine Symfony-Instanz, erstellen Sie Ihre eigene für Domain-Events.

Persönlich mag ich SimpleBus , das Objekte als Ereignisse anstelle einer Zeichenfolge (mit einem Objekt als "Argumente") verwendet. Es folgt auch den Message Bus- und Middleware-Mustern, die viel mehr Optionen für die Anpassung bieten.

PS: Es gibt viele wirklich gute Artikel zu Domain-Events. Google ist dein Freund:)

Beispiel

Normalerweise werden Domänenereignisse in Entitäten selbst aufgezeichnet, wenn eine Aktion für sie ausgeführt wird. Also hätte die Entität Ticket eine Methode wie:

%Vor%

Dies stellt sicher, dass die Entitäten in vollem Umfang für ihren Zustand und ihr Verhalten verantwortlich sind und ihre Invarianten schützen.

Natürlich brauchen wir einen Weg, um die aufgezeichneten Domain Events aus der Entity zu entfernen:

%Vor%

Von hier aus wollen wir wahrscheinlich 2 Dinge:

  • Sammeln Sie diese Ereignisse in einem einzigen Dispatcher / Publisher.
  • Senden / veröffentlichen Sie diese Ereignisse nur nach einer erfolgreichen Transaktion.

Mit Doctrine ORM können Sie einen Listener für Doctrines OnFlush -Ereignis abonnieren, das recordedEvents() für alle gereinigten Entitäten (zum Sammeln der Domain-Ereignisse) und PostFlush , die diese an einen Dispatcher übergeben können, aufruft / Herausgeber (nur wenn erfolgreich).

SimpleBus bietet eine DoctrineORMBridge , die diese Funktionalität bereitstellt.

    
Jasper N. Brouwer 12.10.2016, 22:22
quelle
5

Hatte in letzter Zeit das gleiche architektonische Problem, vorausgesetzt, Sie verwenden Doctrine 2.4+ , ist es am besten, das EventSubscriber nicht zu verwenden (was für alle Events auslöst), aber EntityListeners für die beiden von Ihnen erwähnten Entitäten / p>

Unter der Annahme, dass das Verhalten beider Entitäten gleich sein sollte, könnten Sie sogar einen Listener erstellen und für beide Entitäten konfigurieren. Die Annotation sieht so aus:

%Vor%

Danach können Sie die Klasse TicketNotificationListener erstellen und eine Service-Definition den Rest erledigen lassen:

%Vor%

Sie brauchen hier vielleicht nicht einmal den Entity Manager, da die Entity selbst über die Methode postPersist direkt verfügbar ist:

%Vor%

Weitere Informationen zu Doctrine-Entity-Listenern: Ссылка

    
Rvanlaak 10.10.2016 12:28
quelle