Magento 2 Experten — Hyvä Theme, Tailwind CSS & SEO aus einer Hand ›

Plugin-Reihenfolge (sortOrder) und Konflikte mit anderen Modulen

Plugin-Reihenfolge (sortOrder) und Konflikte mit anderen Modulen

~7 Min. Lesezeit Zuletzt aktualisiert am 9. August 2026

Kapitel 38 hat drei Plugin-Typen an einem einzigen Ziel gezeigt (PointsLedgerRepositoryInterface::getListByCustomerId()) und dabei sortOrder beiläufig vergeben: 10, 20, 30. Dieses Kapitel erklärt, was diese Zahlen tatsächlich bewirken - und was passiert, wenn ein fremdes Modul am selben Ziel mitspielt.

Das Zwiebel-Modell der Ausführung

Magento sortiert alle Plugins eines Ziels aufsteigend nach sortOrder und wickelt sie danach wie eine Zwiebel um den ursprünglichen Methodenaufruf: before-Methoden laufen in aufsteigender sortOrder-Reihenfolge, around-Methoden verschachteln sich so, dass der niedrigste sortOrder die äußerste Schicht bildet, und after-Methoden laufen in absteigender sortOrder-Reihenfolge - spiegelbildlich zur around-Verschachtelung, damit die äußerste Schicht auch das jeweils letzte Wort beim Rückgabewert hat.

Angewendet auf die drei Plugins aus Kapitel 38 (ValidateCustomerIdBeforeGetListPlugin sortOrder 10, CacheLedgerListPlugin sortOrder 20, LimitLedgerListResultPlugin sortOrder 30) läuft ein einzelner Aufruf von getListByCustomerId() in genau dieser Reihenfolge ab:

  1. beforeGetListByCustomerId() (sortOrder 10) validiert $customerId.
  2. aroundGetListByCustomerId() (sortOrder 20) prüft den Request-Cache, ruft bei einem Miss $proceed() auf - das löst die eigentliche Repository-Methode aus.
  3. afterGetListByCustomerId() (sortOrder 30) begrenzt das Ergebnis auf 500 Einträge, bevor es an den ursprünglichen Aufrufer zurückgeht.

Konflikte mit anderen Modulen

Kapitel 39 hat den Checkout-Totals-Collector geplugt, um grand_total direkt zu reduzieren. Nehmen wir an, ein weiteres, unabhängiges (fiktives) "Cashback"-Modul plugt dasselbe Ziel (TotalsCollector::collectAddressTotals()), um ebenfalls einen Rabatt von grand_total abzuziehen. Ohne bewusst gesetzten sortOrder auf beiden Seiten entscheidet die zufällige, modulreihenfolgen-abhängige Standardsortierung, welches Plugin zuerst rechnet - in diesem konkreten Fall unkritisch, da beide Plugins additiv von $result->getGrandTotal() subtrahieren und die Reihenfolge mathematisch keinen Unterschied macht. Sobald aber irgendein beteiligtes Plugin den Rabatt nicht additiv, sondern als feste Zielsumme setzt oder von einem Zwischenwert wie der Zwischensumme statt vom bereits reduzierten grand_total ausgeht, wird die Ausführungsreihenfolge geschäftskritisch.

Achtung: Ohne expliziten sortOrder greift für alle Plugins am selben Ziel der Default-Wert 0 - Ties werden dann durch eine für den Modulentwickler nicht zuverlässig vorhersehbare interne Reihenfolge aufgelöst. Für jedes Plugin, das eine geteilte Ressource wie grand_total verändert, gehört ein expliziter, bewusst gewählter sortOrder zur Pflicht, nicht zur Kür - mit Lücken zwischen den Werten (10, 20, 30 statt 1, 2, 3), damit später ein weiteres Modul dazwischen einhängen kann, ohne bestehende Werte zu verschieben.

Fremde Plugins sichtbar machen

Vor dem Hinzufügen eines eigenen Plugins auf eine bereits vielfach genutzte Core-Klasse lohnt sich ein Blick auf das, was schon registriert ist:

bin/cli bin/magento dev:di:info "Magento\\Quote\\Model\\Quote\\TotalsCollector"

Der Befehl listet alle für eine Klasse registrierten Plugins samt sortOrder und Herkunftsmodul auf - die verlässlichste Quelle, um einen Konflikt vor dem Deployment zu erkennen, statt ihn erst im Live-Betrieb an einer falschen Bestellsumme zu bemerken.

Fremde Plugins gezielt deaktivieren

Ist ein Konflikt unvermeidbar, lässt sich ein fremdes Plugin über denselben name-String plus disabled="true" in der eigenen di.xml abschalten:

<type name="Magento\Quote\Model\Quote\TotalsCollector">
    <plugin name="cashback_apply_cashback_to_totals" disabled="true"/>
</type>

Tipp: Der name-String muss exakt dem entsprechen, den das fremde Modul selbst verwendet - er lässt sich am zuverlässigsten über dev:di:info oder direkt aus der di.xml des fremden Moduls ablesen, niemals raten.

Achtung: Ein fremdes Plugin zu deaktivieren verändert Verhalten, das die Autorinnen und Autoren des anderen Moduls nicht vorhergesehen haben - im konkreten Cashback-Beispiel würde das Deaktivieren stillschweigend die gesamte Cashback-Funktion abschalten, nicht nur den Konflikt lösen. Jede Deaktivierung gehört ausführlich kommentiert und im Idealfall mit dem Hersteller des anderen Moduls abgestimmt.

Damit ist Ordnung und Zusammenspiel von Plugins geklärt. Kapitel 44 schließt Block 5 mit einer letzten, kleineren Frage ab: wann eine klassische Helper-Klasse trotz der ViewModel-Präferenz dieses Projekts noch der richtige Baustein ist.