Factory & Proxy Pattern in Magento 2 | mironsoft.de
Magento 2 · Design Patterns

Factory & Proxy
Pattern in Magento 2

Automatisch generierte Factories für neue Objekte, Proxies für Lazy Loading teurer Services — beide Patterns zusammen erklärt mit konkreten Anwendungsfällen und PHP 8.4.

⏱ 12 Min. Lesezeit PHP 8.4 Magento 2.4.8

1. Factory Pattern: Warum kein new?

In Magento 2 gilt die Regel: Neue Objekte werden nicht mit new erstellt. Der Grund ist fundamental: new KlassenName() umgeht den DI-Container vollständig.

  • Plugins (Interceptors) werden nicht auf das erzeugte Objekt angewendet
  • Die konfigurierte Preference in di.xml wird ignoriert
  • Virtual Types funktionieren nicht
  • Der Shared/Non-Shared Status wird ignoriert

2. Automatisch generierte Factories

Magento 2 generiert Factories automatisch beim Ausführen von bin/magento setup:di:compile oder on-the-fly im Developer Mode. Konvention: Klassenname + "Factory" als Typ-Hinweis deklarieren:

Die generierte Factory sieht (vereinfacht) so aus:

3. Factories richtig verwenden

4. Factory mit initialen Daten

Factories akzeptieren ein optionales $data-Array als Konstruktor-Argument. Besser ist jedoch die explizite Setter-API:

5. Proxy Pattern: Lazy Loading für teure Objekte

Das Proxy Pattern schiebt die Erzeugung eines teuren Objekts auf, bis es wirklich gebraucht wird. Ein Proxy wird als Stellvertreter injiziert — er sieht nach außen genauso aus wie die echte Klasse, erzeugt die echte Instanz aber erst beim ersten Methodenaufruf:

6. Automatisch generierte Proxies

Proxies werden von Magento automatisch generiert. Zwei Wege der Konfiguration:

7. Session-Proxies: der wichtigste Anwendungsfall

Der häufigste Anwendungsfall für Proxies: Session-Objekte. Sie starten PHP-Sessions und beeinflussen HTTP-Response-Header. Werden sie beim Bootstrap instanziiert, entstehen Probleme mit Page-Caching. Session-Objekte immer als Proxy injizieren.

8. Wann einen Proxy verwenden?

  • Session-Objekte: Immer! (CustomerSession\Proxy, CheckoutSession\Proxy, CoreSession\Proxy)
  • Schwere Services: Klassen mit aufwendigen Bootstrap-Operationen im Konstruktor die nur selten gebraucht werden
  • Zirkuläre Abhängigkeiten auflösen: Wenn A von B abhängt und B von A — einen als Proxy injizieren
  • Nicht bei: Leichten Services die sowieso immer gebraucht werden — Proxy-Overhead nicht gerechtfertigt

Mironsoft

Magento 2 Performance & Architektur

Magento 2 Performance analysieren und optimieren?

Wir analysieren Session-Initialisierung, teure DI-Chains und unnötige Objekterzeugungen in Ihrem Magento-Shop und optimieren gezielt mit Factory und Proxy Patterns.

Factory-Analyse

Direktes new ClassName() finden und durch korrekte Factory-Nutzung ersetzen

Session-Proxies

Alle Session-Injektionen auf Proxy umstellen — Page-Cache-Probleme vermeiden

Lazy Loading

Schwere Services identifizieren und durch Proxy-Injection lazy machen

9. Zusammenfassung

Factory und Proxy sind zwei Patterns die den ObjectManager effizient nutzen. Factory für neue Objekte — niemals direkt new. Proxy für Lazy Loading — vor allem für Sessions und schwere Services. Beide werden von Magento automatisch generiert.

Factory & Proxy — Das Wichtigste auf einen Blick

Factory — Neue Objekte

Niemals new Klasse(). Immer $factory->create(). Auto-generiert als KlassennameFactory. Respektiert DI, Plugins, Preferences.

Proxy — Lazy Loading

Teure Klassen lazy instanziieren. Auto-generiert als Klassenname\Proxy. Via di.xml oder direkt als Typ-Hinweis. Pflicht für Session-Objekte.

Session-Proxy

Immer CustomerSession\Proxy statt direkter Session. Gilt für alle Session-Klassen. Verhindert frühzeitige Session-Initialisierung und Page-Cache-Probleme.

setup:di:compile

Nach jeder di.xml-Änderung: bin/magento setup:di:compile. Generiert alle Factories, Proxies und Interceptors. Im Developer Mode on-the-fly generiert.

10. FAQ: Factory & Proxy in Magento 2

1 Muss ich Factories selbst schreiben?
Nein. KlassennameFactory als Typ-Hinweis deklarieren → Magento generiert automatisch in generated/code/. Developer Mode: on-the-fly. Production: bin/magento setup:di:compile.
2 Was passiert bei direktem new ClassName()?
DI-Container wird umgangen: keine Plugins, keine Preferences, kein Virtual Type. Führt zu Fehlern wenn Klasse eigene DI-Abhängigkeiten hat. Immer $factory->create() verwenden.
3 Wann einen Proxy verwenden?
Pflicht: alle Session-Klassen (CustomerSession\Proxy). Sinnvoll: schwere Services die nur manchmal gebraucht werden. Zirkuläre Abhängigkeiten auflösen. Nicht für leichte Services die immer gebraucht werden.
4 Warum Session nicht direkt injizieren?
Session startet PHP-Session im Konstruktor und setzt HTTP-Headers. Bei direkter Injection passiert das beim Bootstrap → Page-Caching funktioniert nicht. Proxy löst das durch Lazy Loading — Session startet erst beim ersten echten Zugriff.
5 Wie erstelle ich eine manuelle Factory?
Eigene Klasse die ObjectManagerInterface injiziert und in create() aufruft. Name muss auf Factory enden. In di.xml als Preference für die auto-generierte Factory registrieren.
6 Factory für ein Interface erstellen?
Ja. PostInterfaceFactory wird auto-generiert wenn PostInterface per Preference an Post gebunden ist. Factory erstellt die konkrete Klasse, gibt Interface-Typ zurück.
7 Wie löst Proxy zirkuläre Abhängigkeiten auf?
A braucht B, B braucht A → Endlosschleife. Lösung: einen als Proxy injizieren. Proxy erstellt echte Instanz erst beim ersten Methodenaufruf — zu dem Zeitpunkt ist die andere Klasse bereits vollständig initialisiert.
8 Factory vs. Proxy — der Unterschied?
Factory: NEUE Instanzen per create() für Non-Injectable Objects. Proxy: Lazy-Wrapper für Injectable Objects — einmalige Instanz, verzögerte Initialisierung. Factory für neue Objekte, Proxy für späte Initialisierung.
9 Nach Factory-Nutzung setup:di:compile nötig?
Developer Mode: automatisch on-the-fly. Production/Staging: bin/magento setup:di:compile nötig. Generierte Dateien in generated/code/ — niemals manuell bearbeiten.
10 Proxy für finale Klassen möglich?
Nein. Proxies werden durch Vererbung erstellt — final class kann nicht erweitert werden. Lösung: eigene Wrapper-Klasse mit der finalen Klasse als Dependency (Komposition statt Vererbung).