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.
Inhaltsverzeichnis
- 1. Das Grundprinzip: Inversion of Control
- 2. Constructor Injection und Property Promotion
- 3. di.xml: Die Konfigurationssprache
- 4. Preferences: Interfaces binden
- 5. Arguments: Konfiguration injizieren
- 6. Virtual Types: Klassen konfigurieren ohne Subklassen
- 7. Shared vs. Non-Shared Objects
- 8. DI-Scopes: global, frontend, adminhtml
- 9. Testing: Mocks und DI
- 10. Häufige Fehler
- 11. Zusammenfassung
- 12. FAQ
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?
2 Warum schlägt setup:di:compile fehl?
3 Plugin vs. Preference — was wählen?
4 Was sind Virtual Types?
5 Wann Factory statt direkter Injection?
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?
Magento\Customer\Model\Session\Proxy in di.xml. Proxy initialisiert Session erst beim ersten Methodenaufruf (Lazy Loading).8 Wie teste ich Klassen mit DI?
$this->createMock(PostRepositoryInterface::class). Klasse direkt instanziieren: new PostManager($repoMock, ...). Kein ObjectManager, kein Datenbankzugriff.9 Was passiert ohne Preference für ein Interface?
"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?
create(). Proxy: Lazy-Loading-Wrapper für Injectable Objects — Instanz erst beim ersten Methodenaufruf. Beide automatisch generiert von Magento.