Christian Renner (ch12r)

Zend Framework – Tutorial 2. Teil – Von der Anfrage zum Controller

zend_framework_tutorial_teil2
Der zweite Teil des Tutorials zum professionellen Einsatz des Zend Frameworks baut auf den ersten Teil auf. In diesem wurde dargestellt, wie das Framework installiert wird. Die Funktionstüchtigkeit wurde dann mit einem obligatorischen “Hello World” geprüft. Des Weiteren wurde kurz dargestellt, wie Controller definiert werden und wie diese implitizit über die URL aufgerufen werden. Auch die View-Komponente wurde ansatzweise behandelt und bereits erste, rudimentäre View-Skripte erstellt.

In diesem Teil wollen wir uns anschauen, wie aus einer Anfrage über verschiedene URL’s bestimmte Controller aufgerufen werden. Daran sind diverse Elemente beteiligt, die wir zum Teil auch schon im ersten Teil des Tutorials benutzt bzw. kennengelernt haben. Auf Grundlagen, wie die Arbeitsweise eines Webservers (HTTP, mod_rewrite) oder die MVC-Architektur werde ich hier nicht eingehen, da diese Themen an genügend anderen Stellen bereits ausführlichst behandelt werden. Zu den im Folgenden behandelten Komponenten des Zend Frameworks zählen: Front-Controller, Request-Objekt, Router, Dispatcher und der Action-Controller.

Der Front-Controller

Durch die erstellten Dateien im ersten Teil des Tutorials haben wir den Webserver derart konfiguriert, dass alle Anfragen, die nicht auf statische Dateien verweisen, von der index.php entgegengenommen werden. Dies stellt eine Realisierung des Frontcontroller-Patterns dar, welche im Falle des Zend Frameworks von der Klasse Zend_Controller_Front übernommen wird. Des Weiteren gilt zu beachten, dass die Klasse als Singleton implementiert ist. Das bedeutet, dass es nur eine einzige Instanz dieser Klasse gibt, die über eine statische Methode referenziert werden kann:

$frontController = Zend_Controller_Front::getInstance();

Danach kann der Front-Controller konfiguriert werden. Dies betrifft zumindest das Setzen eines Pfades zu einem Verzeichnis, das Action-Controller enthält. Da der Front-Controller als Registry eingesetzt wird, kann man zudem bestimmte Objekte und Umgebungsvariablen an diesen übergeben und später wieder abrufen. Wegen seiner Singleton-Eigenschaft sind diese Daten überall in der Anwendung verfügbar.
Folgende, weitere Aufgaben werden vom Front-Controller übernommen:

  • Entgegennehmen der Anfrage
  • Einbinden von Plugins mit Hilfe eines Plugin-Brokers (ErrorHandler, ViewRenderer)
  • Weiterleiten des Request-Objekts an einen Router und einen Dispatcher

Das Request-Objekt

Dieses Objekt der Klasse

Zend_Controller_Request_Http

wird defaultmäßig vom Front-Controller instanziiert und beinhaltet zum einen, wie der Name schon vermuten lässt, die Daten aus dem HTTP-Request (Header-Daten GET/POST-Parameter, Art des Requests, etc.). Des Weiteren enthält das Objekt Informationen, die in der Transformationskette generiert werden, in der es sich befindet:

  • Name des Moduls
  • Name des Controllers
  • Name der Action
  • Weitere Parameter

Diese Werte werden nach und nach von den einzelnen “Beteiligten” der Transformationskette (Front-Controller, Router, Dispatcher, Action-Controller) gesetzt bzw. abgefragt. Das Request-Objekt kann auch manuell erstellt werden und während des Bootstrappings dem Front-Controller übergeben werden. Dies ist ratsam, wenn man HTTP-Requests im Vorfeld bearbeiten möchte oder andere Protokolle (CLI, PHP-GTK) einsetzen möchte. In diesen Fällen erweitert man die Basisklasse (Zend_Controller_Request_Abstract) und übergibt ein entsprechendes Objekt an die

dispatch()

-Methode. In unserem Kontext (Webanwendung) wird dies jedoch nicht benötigt werden.

Das Routing

Mit Routing ist das Extrahieren der aufzurufenden Action an einem bestimmten Action-Controller und der Identifizierung weiterer Parameter gemeint. Übernommen wird diese Aufgabe im Default-Fall vom Standardrouter der Klasse

Zend_Controller_Router_Rewrite

. Dieser setzt ein URL-Rewriting voraus und enthält einen Satz von Regeln, die festlegen, wie die gewünschten Informationen aus einer URL extrahiert werden sollen. Beides wurde bereits im vorangehenden Teil des Tutorials beschrieben. Die Standardrouten können natürlich ergänzt werden. Hierzu stehen dem Entwickler vier Klassen von Routen zur Verfügung:

  • Zend_Controller_Router_Route
  • Zend_Controller_Router_Route_Static
  • Zend_Controller_Router_Route_Regex
  • Zend_Controller_Router_Route_Hostname

Die erste Klasse dient dazu das Standardrouting dahingehend zu erweitern, dass für einen bestimmten Wert, welcher den zu benutzenden Controller entsprechen würde, festgelegt wird, dass der zweite angegebene Wert nicht auf die Action des Controllers verweist, sondern als Parameterübergabe aufgefasst wird.
Beispiel: Für die URL

http://XSampleBlog/search/auto

soll nicht die Action “autoAction” im Controller “searchController” aufgerufen werden, sondern lediglich nach der Phrase “auto” gesucht werden. Hierzu erweitert man den Regelsatz des Routers, um eine entsprechende Route, mittels folgender Anweisung:

$newRoute = new Zend_Controller_Router_Route('search/:phrase', 
    array('controller' => 'search', 'action' => 'index'));
$router->addRoute('search', $newRoute);

Hier wird also durch den Doppelpunkt festgelegt, dass es sich bei dem Wert “auto”, um einen Parameter des Typs “phrase” handelt und am “searchController” die Methode “indexAction” aufgerufen werden soll. Der Parameter “phrase” wird, wie die anderen Werte (Modul-, Controller- und Actionname) auch, im Request-Objekt gespeichert und ist über dieses dann im Action-Controller verfügbar:

// Aufruf im searchController
$request = $this->getRequest();
$phrase = $request->getParam('phrase');

Die anderen Router-Klassen werden ähnlich verwendet. Eine ausführliche Darstellung mit Beispielen findet sich im Programming-Guide des Herstellers.

Der Dispatcher

Der Standard-Dispatcher

Zend_Controller_Dispatcher_Standard

übernimmt anschließend den Part, die vom Router festgestellten Werte für Modul, Controller und Action aus dem Request-Objekt auszulesen und die entsprechende Methode aufzurufen. Fehlende Werte werden durch defaults aufgefüllt. Diese Default-Werte können mittels entsprechenden Setter-Methoden gesetzt werden. Ansonsten sind die Default-Werte wie folgt gesetzt:

  • ‘default’ für Modul
  • ‘index’ für Controller
  • ‘index’ für Action

Der Dispatcher sitzt am Ende der Transformationskette des Request-Objekts bevor es an den jeweiligen Action-Controller weitergegeben wird. Mittels der Methode

forward()

kann diese Transformationskette aus dem Action-Controller heraus erneut angestoßen werden.

Der Action-Controller

Die Aufgaben des Action-Controllers sind im Prinzip erst einmal unklar. Es ist allein eine Designfrage, welche Aufgabe man ihm zuspricht. Ich habe erst letztens gelesen, dass man ihm eigentlich so wenig wie möglich Logik zuweisen und die Businesslogik in das Modell verlegen soll. Der Vorteil, der bei sogenannten “Fat Models” entstehe, liege in der höheren Modularisierungs- und der damit verbundenen Re-Use-Fähigkeit. Die Aufgaben des Controllers liegen dann nur in der Zuteilung der jeweiligen Modelklassen zu einer Anfrage. Für jetzt und hier ist dieses Thema jedoch noch zu früh. Auf sinnvolle Architekturen werde ich in einem späteren Teil des Tutorials noch einmal eingehen.

Im Wesentlichen liegt die Aufgabe des Controllers darin, der View-Komponente zu sagen, was sie darstellen soll. Diese Erkenntnis gewinnt er unmittelbar aus dem Request-Objekt und aus dem was der Entwickler festgelegt hat, was er in entsprechenden Fällen zu tun hat. Entsprechend der Anfrage zieht er also das eine oder andere Model-Objekt aus dem Speicher, modifiziert es gegebenenfalls oder erweitert das Datenmodell anhand der im Request-Objekt übermittelten Daten und übergibt diese Teilmenge dem View-Skript. Das wars. Mehr macht der Controller nicht. Ob man dieses Zusammensuchen und Transformieren von Daten nun in eine eigene Modelklasse auslagert, bleibt dann denke ich jedem selbst überlassen.

So das war es für dieses Mal. Ich hoffe euch hat das eher etwas theoretische Tutorial einen Einblick verschaffen können, welche Aufgaben die einzelnen Komponenten des Zend Frameworks übernehmen. Bei Fragen oder Problemen darf natürlich gerne ein Kommentar hinterlassen werden. Der nächste Teil folgt in den nächsten Tagen. Bis dahin wünsche ich allen ein gutes Gelingen.

This entry was posted in Development and tagged , , , , . Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

2 Comments

  1. Posted 7. May 2009 at 09:05 | Permalink

    Danke für das Spitzen-Tutorial!
    Hat mir viel weitergeholfen und ein wahrer Gold-Fund unter den ganzen Zend-Tutorial-Krüppeln im Netz.
    Beide Daumene hoch. =)

  2. Posted 7. May 2009 at 09:13 | Permalink

    Vielen Dank für das Lob. Ich bin nach einiger Zeit der Durststrecke im Moment dabei die weiteren Teile zu verfassen.
    Ich denke im Juni haben sie die notwendige Reife, um veröffentlicht zu werden.

Post a Comment

Your email is never published nor shared.

You may use these HTML tags and attributes <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="">