Matti Mäkitalo: PHP-Klassen in Framework global verfügbar machen

Beitrag lesen

Hallo,

entschuldige die späte Antwort, ich schaue nicht jeden Tag hier rein.

Singleton

In den erwähnten Videos wird der wichtige Unterschied zwischen Singleton (dem Pattern) und einem singleton (ein Objekt, welches nur einmal existieren darf) gemacht. Letzteres ist je nach Anwendungsfall durchaus sinnvoll. Als Beispiel sei ein Cache genannt (wenn mehrere Caches für dieselbe Sache existieren ist der Cache schnell nutzlos). Das (Anti-)Pattern hingegen ist unnötig.

Laravel

Damit habe ich keine Erfahrungen. Die Schnippsel, die ich gesehen habe, fande ich eher meh (statische Funktionen, viel Magie). Ich bin (war, habe seit knapp 9 Jahren kein PHP-Projekt mehr gemacht) großer Freund von Symfony und empfehle daher das. Und da ist auch vglw. wenig Magie drinnen.

Deswegen arbeite ich in solchen Situationen auch gerne mit einem Context-Objekt, wo alle "globalen" Dinge drin stecken und der an alle Objekte durchgereicht wird, die im Verlauf der Requestverarbeitung entstehen.

So ein Kontext-Objekt macht die Abhängigkeit zwar klar, aber macht die Testbarkeit nicht wirklich einfacher als wenn man viele globale Variablen hat. Ohne den Code zu kennen weiß man immer noch nicht, welche Teile des Kontext-Objekts verwendet werden, und deswegen muss man im Zweifel alle irgendwie belegen. Das macht den Test unnötig schwierig.

Damit das funktioniert und testbar bleibt, muss man dann natürlich den DI Container überallhin durchschleifen und darf ihn nicht als globalen State missbrauchen.

Diesen Satz würde ich gerne hinterfragen, da er so klingt als ob hier DI falsch verwendet wird (aber vielleicht lese ich auch etwas anderes hinein als gemeint ist). In einer ordentlichen DI-Welt sollte man nie einen DI-Container ("Service Locator") irgendwo injecten oder damit arbeiten, da der Grundsatz "don't look for things" gilt. Wenn eine "Bean" (ein instanziiertes Objekt mit seinen Abhängigkeiten) irgendwo gebraucht wird dann injected man dieses. Aber nie den DI-Container/Service-Locator irgendwo injecten und dann die Bean abfragen.

Sprich: dein Business-Code sollte sowohl frei von DI-Container/Service-Locator sein als auch (mit Ausnahme von Factories und von simplen Value-Objekten) von Objekt-Instanziierungen (new bzw. ein Konstruktor ist im Grunde nichts anderes als eine statische Methode und verhindert die Austauschbarkeit der Klasse.

VG Matti