Was ist ein DI Container?
Ein Dependency Injection Container (DIC) ist eine Klasse, die Objekte instanziieren und konfigurieren kann.
Es mag Sie überraschen, aber in vielen Fällen benötigen Sie keinen Dependency Injection Container, um die Vorteile der Dependency Injection (kurz DI) zu nutzen. Schon im Einführungskapitel haben wir DI anhand konkreter Beispiele gezeigt, und es wurde kein Container benötigt.
Wenn Sie jedoch eine große Anzahl verschiedener Objekte mit vielen Abhängigkeiten verwalten müssen, wird ein Dependency Injection Container wirklich nützlich sein. Dies ist beispielsweise bei Webanwendungen der Fall, die auf einem Framework basieren.
Im vorherigen Kapitel haben wir die Klassen Article
und UserController
vorgestellt. Beide haben
einige Abhängigkeiten, nämlich die Datenbank und die Fabrik ArticleFactory
. Und für diese Klassen werden wir nun
einen Container erstellen. Natürlich ist es für ein so einfaches Beispiel nicht sinnvoll, einen Container zu haben. Aber wir
werden ihn erstellen, um zu zeigen, wie er aussieht und funktioniert.
Hier ist ein einfacher hardcodierter Container für das gegebene Beispiel:
Die Verwendung würde folgendermaßen aussehen:
Wir fragen den Container nur nach dem Objekt und müssen nichts mehr darüber wissen, wie es erstellt wird oder welche Abhängigkeiten es hat; das alles weiß der Container. Die Abhängigkeiten werden vom Container automatisch injiziert. Darin liegt seine Stärke.
Bisher hat der Container alle Daten fest codiert. Wir werden also den nächsten Schritt machen und Parameter hinzufügen, damit der Container wirklich nützlich wird:
Aufmerksame Leser haben vielleicht ein Problem bemerkt. Jedes Mal, wenn ich ein UserController
-Objekt erhalte,
werden auch eine neue Instanz von ArticleFactory
und der Datenbank erstellt. Das wollen wir definitiv nicht.
Wir fügen daher eine Methode getService()
hinzu, die immer dieselben Instanzen zurückgibt:
Beim ersten Aufruf von z. B. $container->getService('Database')
lässt sie von createDatabase()
das Datenbankobjekt erstellen, speichert es im Array $services
und gibt es beim nächsten Aufruf direkt zurück.
Wir passen auch den Rest des Containers an, um getService()
zu verwenden:
Übrigens wird der Begriff Dienst (Service) für jedes Objekt verwendet, das vom Container verwaltet wird. Daher auch der Name
der Methode getService()
.
Fertig. Wir haben einen voll funktionsfähigen DI-Container! Und wir können ihn verwenden:
Wie Sie sehen, ist es nicht kompliziert, einen DIC zu schreiben. Es sei daran erinnert, dass die Objekte selbst nicht wissen, dass sie von einem Container erstellt werden. Daher ist es möglich, jedes Objekt in PHP auf diese Weise zu erstellen, ohne seinen Quellcode zu ändern.
Das manuelle Erstellen und Warten einer Containerklasse kann schnell zu einem Albtraum werden. Im nächsten Kapitel werden wir daher über den Nette DI Container sprechen, der sich fast von selbst generieren und aktualisieren kann.