© saicle/Shutterstock.com
Ein Überblick über den ServiceManager vom Zend Framework 2

Stets zu Diensten


In diesem Artikel erfahren Sie zuerst einige grundlegende Informationen zum Einsatz des ServiceManagers und möglichen Fallstricken. Der Artikel zeigt auf, welche spezialisierten ServiceManager es gibt und wie Sie diese gewinnbringend einsetzen können. Zudem wird erläutert, wie hilfreich Initializer sein können und warum Sie den Einsatz vom „berüchtigten“ ServiceLocatorAwareInterface eher vermeiden sollten.

Die Komponente Zend\ServiceManager hat im Zend Framework 2 die alte statische Zend_Registry vollkommen ersetzt. Der ServiceManager ermöglicht dem Entwickler, die Konfiguration und Initialisierung seiner Objekte und Services an einem zentralen Ort zu bündeln. Das erleichtert die Wiederverwendung und hilft bei der Strukturierung der eigenen Anwendung.

ZF2-Beispielanwendung

Damit Sie die Beispiele selbst nachvollziehen können, steht eine Beispielanwendung auf GitHub für Sie bereit [1]. Sie können das Projekt wie folgt klonen (bitte ggf. die Verzeichnisse anpassen) und installieren:

> cd /home/devhost > git clone https://github.com/RalfEggert/phpmagazin.service-manager > cd phpmagazin.service-manager > php composer.phar selfupdate > php composer.phar install > sudo chmod 777 -R data/ 

Danach richten Sie noch einen Virtual Host für die Adresse phpmagazin.service-manager ein. Wenn Sie nun http://phpmagazin.service-manager/ in Ihrem Browser aufrufen, sollte die Seite ungefähr wie in Abbildung 1 aussehen. Nun können wir loslegen.

eggert_zf2_1.tif_fmt1.jpgAbb. 1: Beispielanwendung im ZF2

Zuerst etwas Theorie

Die Zend\ServiceManager-Komponente [2] implementiert das ServiceLocator-Entwurfsmuster, das unter anderem auch von Martin Fowler beschrieben wurde [3]. Der ServiceLocator hat die Aufgabe (ähnlich wie eine Registry), alle benötigten Objekte (Services) bereitzustellen. Während eine Registry diese Objekte zuerst übergeben bekommen muss, um sie dann für die spätere Verwendung bereitzuhalten, kümmert sich der ServiceLocator auch um die Instanziierung dieser Objekte. Der ServiceLocator hält somit nicht nur die instanziierten Objekte, sondern auch das Wissen bereit, wie ein Objekt zu instanziieren ist. Erst wenn diese Objekte wirklich gebraucht werden, werden diese erzeugt.

Der ServiceManager ist dabei in der Lage, sowohl Klassen ohne Abhängigkeiten direkt zu instanziieren (die so genannten Invokables) als auch Klassen mit Abhängigkeiten mithilfe von Factories zu generieren. Zusätzlich werden abstrakte Fabriken und Initializer unterstützt, sie können für jeden Service definieren, ob dieser nach der Instanziierung mehrfach genutzt werden darf oder nicht, sowie auch fertig generierte Objekte übergeben. Die Konfiguration des ServiceManagers kann sowohl über Konfigurationsklassen als auch über Konfigurationsdateien erfolgen.

Übrigens werden die Begriffe ServiceLocator und ServiceManager im ZF2 nahezu synonym verwendet. Wenn vom ServiceLocator die Rede ist bzw. eine Methode oder ein Parameter als ServiceLocator bezeichnet ist, ist damit meistens der konkrete ServiceManager gemeint, der im MVC konfiguriert und bereitgestellt wird. Im Folgenden werden diese beiden Begriffe auch synonym verwendet.

Servicemanager konfigurieren

Um die grundlegenManager verstehen zu können, benötigen wir als Erstes einige Beispielklassen, mit denen wir arbeiten können. Als Erstes verwenden wir eine Shop\Entity\PinkPrincessBell (Listing 1), die ohne Konstruktor auskommt und somit direkt instanziiert werden kann.

Die Klasse repräsentiert eine Fahrradklingel und implementiert das Shop\Entity\BellInterface. Als Nächstes setzen wir die Klasse Shop\Entity\Wheel ein (Listing 2), deren Konstruktor einen Namen und die Reifengröße benötigt, damit die Klasse instanziiert werden kann. Auch hier wird ein entsprechendes Interface mit Namen Shop\Entity\WheelInterface implementiert. Als Letztes im Bunde verwenden wir die Klasse Shop\Entity\Bike (Listing 3), die einen etwas komplexeren Konstruktor bereitstellt. Unter anderem werden auch Instanzen von den anderen Klassen benötigt. Dabei kommen das BellInterface und das WheelInterface als Type Hint zum Einsatz, was die Testbarkeit und Wartbarkeit der Klasse erhöht, da wir somit gegen ein Interface und nicht gegen eine konkrete Klasse programmieren. Zusätzlich werden auch noch Name und Farbe als Parameter benötigt. Die Sinnhaftigkeit dieser Klassen wollen wir an dieser Stelle nicht weiter diskutieren, sie dienen für die folgenden Erläuterungen lediglich als Grundlage. Sie finden alle Klassen in der Beispielanwendung im Verzeichnis /module/Shop/src/Shop/Entity.

Um diese Klassen mithilfe des ServiceManagers verwenden zu können, müssen wir als Nächstes die Konfiguration in der Datei /module/Shop/config/­module.config.php betrachten (Listing 4). Beim Laden der aktiven Module der Zend-Framework-2-Anwendung wird die Konfiguration für den ServiceManager durch den Konfigurationsschlüssel service_manager ausgezeichnet. Darunter werden die weiteren Konfigurationsschlüssel definiert. Mit invokables legen Sie fest, welche Klassen direkt instanziiert werden können. Dies betrifft in unserem Beispiel nur die Klasse PinkPrincessBell.

Für Klassen, die nur mithilfe eines Konstruktors instanziiert werden können, oder die über entsprechende Setter-Methoden konfiguriert werden müssen, kommt der Schlüssel factories zum Einsatz. Dies betrifft die beiden definierten Reifen und die beiden Fahrräder. Bei der Implementation der Factories haben Sie die Wahl zwischen Closures und Factory-Klassen. Für die Reifen wird jeweils eine Factory Closure definiert, die eine Instanz von Shop\Entity\Wheel generiert, dabei den Namen und die Größe festlegt und abschließend zurückgibt. Für die beiden konfigurierten Fahrräder kommen Factory-Klassen zum Einsatz. Ei...

Neugierig geworden? Wir haben diese Angebote für dich:

Angebote für Teams

Für Firmen haben wir individuelle Teamlizenzen. Wir erstellen Ihnen gerne ein passendes Angebot.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang