Observer-Reihenfolge und Priorität steuern
Observer-Reihenfolge und Priorität steuern
~6 Min. Lesezeit Zuletzt aktualisiert am 9. August 2026
Kapitel 35 zeigte, dass ein einziges Event mehrere unabhängige Observer haben kann - mironsoft_loyalty_customer_tier_changed könnte gleichzeitig ein Marketing-Modul UND ein Analytics-Modul interessieren. Was, wenn deren Reihenfolge zueinander tatsächlich wichtig ist? Die kurze Antwort: events.xml kennt - anders als Plugins - kein explizites sortOrder-Attribut. Dieses Kapitel erklärt, wovon die Reihenfolge stattdessen abhängt.
Reihenfolge innerhalb einer Datei
Registriert dieselbe events.xml-Datei mehrere <observer>-Knoten für dasselbe <event>, laufen sie exakt in der Reihenfolge, in der sie im Dokument stehen - top-down, vorhersehbar.
Reihenfolge über Module hinweg
Registrieren zwei verschiedene Module je einen Observer auf dasselbe Event, bestimmt die Modul-Ladereihenfolge die Ausführungsreihenfolge - dieselbe topologische Sortierung aus den <sequence>-Einträgen in module.xml, die auch di.xml- und Layout-Merges steuert. Ein Modul, das nach Mironsoft_Loyalty laden soll, trägt es einfach in seine eigene sequence ein:
<!-- app/code/Vendor/Analytics/etc/module.xml, illustrativ -->
<module name="Vendor_Analytics">
<sequence>
<module name="Mironsoft_Loyalty"/>
</sequence>
</module>Damit ist garantiert, dass Vendor_Analytics' Observer auf mironsoft_loyalty_customer_tier_changed immer nach einem eventuellen eigenen Observer von Mironsoft_Loyalty auf demselben Event läuft - ohne eine einzige Zeile events.xml selbst anzufassen.
Das name-Attribut als Merge-Schlüssel
Zwei <observer>-Knoten mit demselben name - auch aus verschiedenen Modulen - werden zu einem einzigen zusammengeführt, exakt wie bei Block- und Layout-XML. Ein später ladendes Modul kann so einen fremden Observer per disable="true" abschalten oder seine instance überschreiben, ohne dessen Quellcode zu verändern.
<!-- Ein Observer eines anderen Moduls gezielt deaktivieren, illustrativ -->
<event name="mironsoft_loyalty_customer_tier_changed">
<observer name="vendor_marketing_notify_tier_upgrade" disable="true"/>
</event>Das shared-Attribut
Standardmäßig (shared="true", implizit) wiederverwendet Magento eine einzige Observer-Instanz für alle Dispatches - unkritisch für AwardPointsOnOrderPlaced und ReversePointsOnCreditmemoSave, da beide ausschließlich über Konstruktor-Injection arbeiten und keinerlei veränderlichen Zustand zwischen zwei Aufrufen halten - dieselbe Zustandslosigkeit, die PointsCalculator (Kapitel 5) von Anfang an auszeichnet. shared="false" erzwingt eine frische Instanz je Dispatch und wäre nur relevant, wenn ein Observer tatsächlich eigenen, veränderlichen Zustand zwischen execute()-Aufrufen hält - in diesem Modul kommt das nirgends vor.
Wenn Reihenfolge wirklich zählt
- Modul-
sequenceanpassen (siehe oben) - wirkt sich aber auf alle geteilten Events zwischen den beiden Modulen aus, nicht nur den einen, der gerade wichtig ist. - Beide Anliegen in einem einzigen Observer bündeln, statt sich auf eine Reihenfolge zwischen zwei getrennten Observern zu verlassen - eliminiert das Problem, kostet aber Entkopplung.
- Wirklich reihenfolgekritische Logik in ein Plugin verschieben, das ein explizites, numerisches
sortOrderkennt (Kapitel 37 leitet direkt dorthin über).
Tipp: Diese drei Optionen sind eine Rangfolge, keine gleichwertige Auswahl: Option 1 zuerst versuchen, Option 2 nur bei echter inhaltlicher Kohäsion beider Anliegen, Option 3 als letztes Mittel, wenn Reihenfolge tatsächlich Kernanforderung ist - nicht bloß eine bequeme Annahme.
Damit endet Block 4 inhaltlich fast - Kapitel 37 fasst die gesamte, bisher implizite Entscheidung "Observer oder Plugin?" explizit zusammen, bevor Block 5 mit Plugins im Detail beginnt.