Dependency Injection in Magento 2: di.xml, Interfaces und Shared Objects tief erklärt
Magento 2 · Design Patterns

Dependency Injection
in Magento 2

Das Fundament aller Magento-Architektur: Constructor Injection, di.xml, Preferences, Virtual Types, Shared Objects und sauberes Testing mit Mocks — vollständig erklärt.

⏱ 15 Min. Lesezeit PHP 8.4 Magento 2.4.8

1. Das Grundprinzip: Inversion of Control

DI ist eine konkrete Umsetzung des Inversion of Control (IoC) Prinzips: Statt dass eine Klasse ihre Abhängigkeiten kontrolliert (erzeugt, konfiguriert), übernimmt ein übergeordneter Container diese Kontrolle und „injiziert" die Abhängigkeiten von außen.

  • Testbarkeit: Im Test kann man eine Mock-Implementierung injizieren, ohne die Klasse selbst zu ändern.
  • Austauschbarkeit: Die Implementierung hinter einem Interface kann per Konfiguration ausgetauscht werden.
  • Lose Kopplung: Klassen kennen nur das Interface, nicht die konkrete Implementierung.
  • Deklarative Konfiguration: Welche Klasse für welches Interface gilt, steht in XML — übersichtlich und zentral.

2. Constructor Injection und Property Promotion

Magento 2 unterstützt ausschließlich Constructor Injection. Property Injection und Setter-Injection werden nicht verwendet. Der Konstruktor ist der einzige Ort, an dem alle Abhängigkeiten einer Klasse sichtbar sind. Ab PHP 8.1 kombiniert Constructor Property Promotion Deklaration und Zuweisung in einer Zeile:

3. di.xml: Die Konfigurationssprache des DI-Containers

Die di.xml-Datei ist die zentrale Konfigurationsdatei für den ObjectManager. Sie beschreibt, welche konkreten Klassen für Interfaces verwendet werden, wie Argumente übergeben werden und welche Plugins aktiv sind:

4. Preferences: Interfaces an Implementierungen binden

Ein <preference>-Element bindet ein Interface an eine konkrete Implementierung. Wenn der ObjectManager eine Klasse mit diesem Interface als Abhängigkeit instanziieren soll, verwendet er die konfigurierte Preference:

5. Arguments: Konfiguration injizieren

Mit <arguments> kann man bestimmten Klassen spezifische Instanzen oder Konfigurationswerte übergeben:

6. Virtual Types: Klassen konfigurieren ohne Subklassen

Ein Virtual Type ist eine „virtuelle" Klasse ohne eigene PHP-Datei — sie konfiguriert eine bestehende Klasse mit anderen Constructor-Argumenten. Ideal für Logger, API-Clients und konfigurierbare Services:

7. Shared vs. Non-Shared Objects

Standardmäßig erstellt der ObjectManager für jede Klasse nur eine Instanz (Shared). Für Services und Repositories ideal — sie haben keinen Zustand. Für Entities und DTOs braucht man bei jedem Aufruf eine neue Instanz — dafür gibt es Factories:

8. DI-Scopes: global, frontend, adminhtml

di.xml-Dateien werden nach Area (Scope) getrennt. Unterschiedliche Scopes ermöglichen verschiedene Implementierungen für Frontend und Backend:

9. Testing: DI ermöglicht saubere Unit-Tests

Der größte praktische Vorteil von DI: Mock-Objekte können als Ersatz für echte Implementierungen injiziert werden. Kein Datenbankzugriff, keine Filesystem-Operationen — saubere, schnelle Unit-Tests:

10. Häufige Fehler bei Dependency Injection

Fehler 1: ObjectManager direkt verwenden

Fehler 2: Konkrete Klassen statt Interfaces injizieren

Fehler 3: Session-Objekte direkt injizieren

Mironsoft

Magento 2 Architektur & Code-Qualität

Magento-Code-Review oder Architekturberatung?

Wir analysieren bestehenden Magento-Code auf DI-Anti-Patterns, ObjectManager-Missbrauch und Upgrade-Risiken. Klare Handlungsempfehlungen und Migrations-Roadmap inklusive.

DI-Audit

ObjectManager-Aufrufe, Core-Overrides und zirkuläre Abhängigkeiten identifizieren

Architektur-Review

di.xml-Konfiguration, Preference vs. Plugin Entscheidungen, Virtual Type Design

Unit Tests

Testbare DI-Architektur einführen — PHPUnit Mocks, Testabdeckung aufbauen

11. Zusammenfassung

Dependency Injection ist das Fundament aller Magento 2 Entwicklung. Es ermöglicht lose Kopplung, Testbarkeit und Austauschbarkeit durch konsequente Constructor Injection, Interface-Bindungen per di.xml und automatisch generierte Factories und Proxies.

Dependency Injection — Das Wichtigste auf einen Blick

Constructor Injection

Immer über den Konstruktor. Constructor Property Promotion nutzen. readonly für unveränderliche Abhängigkeiten. Nie direkter ObjectManager-Aufruf.

Interfaces > Implementierungen

Immer das Interface injizieren, nie die Implementierung direkt. Binding via <preference> in di.xml. Core-Preferences vermeiden — Plugin bevorzugen.

Factory für neue Objekte

Data-Objekte niemals direkt injizieren — immer Factory verwenden. Auto-generiert für alle Klassen: KlassennameFactory. create() gibt neue Instanz.

Virtual Types

Klassen konfigurieren ohne PHP-Code. Ideal für Logger, Decorators, Wrapper mit verschiedenen Konfigurationen. Nur in di.xml — keine PHP-Datei nötig.

12. FAQ: Dependency Injection in Magento 2

1 Was ist der ObjectManager?
Magentos DI-Container — liest Typ-Hinweise im Konstruktor und instanziiert Abhängigkeiten automatisch. Niemals direkt aufrufen (außer Factories, Bootstrap). Immer Constructor Injection verwenden.
2 Warum schlägt setup:di:compile fehl?
Häufig: Typen-Fehler im Konstruktor, falsche Klassennamen in di.xml, zirkuläre Abhängigkeiten. Fehlermeldung zeigt die Klasse. Lösung: di.xml prüfen, zirkuläre Abhängigkeit durch Proxy oder Event lösen.
3 Plugin vs. Preference — was wählen?
Preference = Klasse komplett ersetzen (Konflikte möglich). Plugin = Verhalten vor/nach/um Methode hinzufügen (kombinierbar). Interfaces binden: Preference. Core-Verhalten ändern: Plugin.
4 Was sind Virtual Types?
Konfigurierte Klassen-Varianten ohne PHP-Code — nur in di.xml. Dieselbe Klasse mit anderen Constructor-Argumenten. Ideal für Logger, API-Clients mit verschiedenen Endpoints — kein Klassen-Duplikat nötig.
5 Wann Factory statt direkter Injection?
Für Non-Injectable Objects (Model, Entity, Collection). Direkte Injection liefert immer dieselbe Instanz. Factory::create() gibt jedes Mal eine neue, leere Instanz. Magento generiert Factories automatisch.
6 Bereichsspezifische DI-Konfiguration?
etc/frontend/di.xml, etc/adminhtml/di.xml, etc/webapi_rest/di.xml. Bereichsspezifisch hat Vorrang vor global (etc/di.xml). Für verschiedene Implementierungen je Scope.
7 Wie Session korrekt injizieren?
Niemals direkt — beeinflusst Bootstrap. Proxy verwenden: Magento\Customer\Model\Session\Proxy in di.xml. Proxy initialisiert Session erst beim ersten Methodenaufruf (Lazy Loading).
8 Wie teste ich Klassen mit DI?
PHPUnit Mocks erstellen: $this->createMock(PostRepositoryInterface::class). Klasse direkt instanziieren: new PostManager($repoMock, ...). Kein ObjectManager, kein Datenbankzugriff.
9 Was passiert ohne Preference für ein Interface?
DI-Container wirft Exception: "Cannot instantiate interface X". Jedes Interface braucht eine Preference-Bindung. Preference gehört in die di.xml des Moduls das das Interface definiert.
10 Proxy vs. Factory — der Unterschied?
Factory: neue Instanzen von Non-Injectable Objects per create(). Proxy: Lazy-Loading-Wrapper für Injectable Objects — Instanz erst beim ersten Methodenaufruf. Beide automatisch generiert von Magento.