Heute soll es um Dependency Injection in Contao 4 gehen. In Symfony heißt der Dependency Injection Container "Service Container" und die darüber bezogenen Klassen werden als "Services" bezeichnet. Wie man Services anlegt und verwendet, will ich nun zeigen. Auch bei diesem Artikel handelt es sich um zusammengetragene Inforationen und nicht um "der Weisheit letzten Schluss". Wenn also jemand Verbesserungsvorschläge hat, würde ich mich über eine Nachricht sehr freuen.
Vorbereitung
Wie immer gibt es mehrere Weg zum Ziel. Ich möchte die Services im Bundle konfigurieren und diese Konfiguration in die
globale einbinden. Um dies zu erreichen, wird zunächst die Datei app/config/config.yml
angepasst. Ganz oben wird die
Rubrik imports
wie folgt ergänzt (Zeile 5):
In Zeile 5 binden wir die Konfiguration unserer Services ein. Nun erstellen wir die Datei
src/Acme/TestBundle/Resources/config/services.yml
.
src/Acme/TestBundle/Resources/config/
und nicht
src/Acme/TestBundle/Resources/contao/config/
gemeint! (Dies ist die Standarddatei für Services in
Symfony.)
Konfiguration
In Zeile 4 wird ein Parameter definiert, dieser kann später an Services übergeben oder über den Service-Container bezogen
werden. Diese Art der globalen Datenhaltung kennen aus Contao 3, wo sie mittels des Arrays $GLOBALS
gelöst wird. In
Zeile 8 definieren wird dann unseren Service in dem wir in Zeile 9 die Klasse angeben und in Zeile 11 übergeben wir
dann den in Zeile 4 definierten Parameter.
Service-Klasse
Nun erstellen wir die Klasse für den Service.
Die Klasse ist bewusst einfach gehalten. Es gibt eine Eigenschaft für den Text (Zeile 7), er wird in Zeile 9 über den Konstruktor gesetzt. Dies erledigt der Service-Container und verwendet dafür unseren Parameter. In Zeile 14 beginnt die Methode, die den Parameter ausgibt.
Verwendung
Wollen wir nun in einer Klasse diesen Service benutzen, können wir dies z.B. so lösen:
In diesem Inhaltselement wird in Zeile 20 der Service über den Container bezogen und in Zeile 21 die Methode aufgerufen.
Dependency Injection
Bis jetzt ging es nur um Services. Da ein Service an sich noch nicht viel mit Dependency Injection zu tun hat, wollen wir nun unseren Service in eine andere Klasse "injecten".
Service-Klasse
Wir erstellen die Klasse src/Acme/TestBundle/classes/AcmeMultiGreeter.php
. Diese Klasse bekommt den AcmeGreeter
und
eine Anzahl. Sie soll dann entsprechend oft grüßen.
In Zeile 10 werden vom Service-Container die Anzahl und die Klasse Acme\TestBundle\classes\AcmeGreeter
übergeben. In
Zeile 18 beginnt die For-Schleife und in Zeile 19 wird die Methode für das Grüßen aufgerufen.
Konfiguration
Nun müssen wir den Service noch konfigurieren. Dafür ändern wir die Datei src/Acme/TestBundle/Resources/config/services.yml
.
In Zeile 5 erstellen wir einen neue Parameter für die Anzahl. In Zeile 14 beginnt die Konfiguration des neuen Services. In Zeile 15 steht wider die Klasse und ab Zeile 16 sind die Parameter aufgeführt. Neu ist, dass wir in Zeile 17 einen anderen Service übergeben. Der Container kümmert sich nun um die Instanzierung der Abhängigkeiten und alles weitere.
Verwendung
Wir können nun in unserem Inhaltselement den neuen Service benutzen.
Hier hat sich nur die Zeile 20 geändert. Wir lassen uns statt des acme_test.greeter
nun den acme_test.multigreeter
geben. Der Rest läuft automatisch.
Debuggen
Will man die Konfiguration der Services überprüfen, gibt es dafür den folgenden Konsolenbefehl:
Kommentare
Aufgrund der unklaren Rechtslage durch die DSGV habe ich mich entschlossen, die Kommentare bis auf Weiteres zu deaktivieren.