7.4. Bereitgestellte Unterklassen
Zurück | Kapitel 7. Zend_Controller | Weiter

## 7.4. Bereitgestellte Unterklassen

### 7.4.1. Einführung

Das Zend Framework stellt verschiedene Alternativen zu den bereit gestellten Standardklassen zur Verfügung. Dies beinhaltet altive Request Objekte, Router und Response Objekte.

### 7.4.2. Zend_Controller_Request_Http

#### 7.4.2.1. Einführung

`Zend_Controller_Request_Http` stellt ein Request Objekt für die Verwendung in einer HTTP Umgebung bereit. `Zend_Controller_Request_Http` ist die Standard Request Klasse, die von `Zend_Controller_Dispatcher` verwendet wird.

#### 7.4.2.2. Auf Request Daten zugreifen

`Zend_Controller_Request_Http` kapselt den Zugriff auf relevante Werte wie der Schlüssel und Wert für Controller und Action Variablen des Routers und alle zusätzlichen Parameter, die aus der URI ermittelt wurden. Durch den Proxy zu `Zend_Controller_Request_Http` erlaubt es zusätzlich den Zugriff auf superglobale Werte als öffentliche Eigenschaften und verwaltet die aktuelle Basis URL und Request URI. Superglobale Werte können in einem Request Objekt nicht gesetzt werden, stattdessen verwendet man die setParam/getParam Methoden um Benutzerparameter zu setzen oder zu erhalten.

| Superglobale Daten
Beim Zugriff auf superglobale Daten über die öffentlichen Eigenschaften von `Zend_Controller_Request_Http` ist es notwendig, darauf zu achten, dass der Eigenschaftsname (der superglobale Arrayschlüssel) einem superglobalen Wert in einer bestimmten Reihenfolge entspricht: 1. GET, 2. POST, 3. COOKIE, 4. SERVER, 5. ENV.

Auf spezifische superglobale Werte kann alternativ über eine öffentliche Methode zugegriffen werden. Zum Beispiel kann auf den unverarbeitete Wert von `$_POST['user']` durch Aufruf der `getPost('user')` Methode des Request Objekts zugegriffen werden.

#### 7.4.2.3. Basis Url und Unterverzeichnisse

`Zend_Controller_Request_Http` erlaubt, dass Zend_Controller_RewriteBase in einem Unterverzeichnis verwendet werden kann. Zend_Controller_Request_Http versucht, die Basis URL automatisch zu erkennen und entsprechend zu setzen.

Wenn man zum Beispiel seine `index.php` in einem Webserverunterverzeichnis mit Namen `/projects/myapp/index.php` verwendet, sollte die Basis URL (die Rewrite Basis) auf `/projects/myapp` gesetzt werden. Dieser String wird dann vom Anfang des Pfades entfernt, bevor irgend welche Routingtreffer ermittelt werden. Dies befreit einem davon, es an den Anfang jeder Route setzen zu müssen. Eine Route `'user/:username'` passt auf URIs wie `http://localhost/projects/myapp/user/martel` und `http://example.com/user/martel`.

| URL Erkennung beachtet Groß- und Kleinschreibung
Die automatische Erkennung der Basis URL beachtet die Groß- und Kleinschreibung, weshalb man sicherstellen sollte, dass die URL einem Unterverzeichnis im Dateisystem entspricht (sogar auf einem Windows Rechner). Andernfalls wird auf die noRoute aktion umgeleitet.

Sollte die Basis URL falsch erkannt werden, kann man diese auch mit einem eigenen Pfad mit Hilfe der `setBaseUrl()` Methode der `Zend_Controller_Request_Http` Klasse oder der `Zend_Controller_Front` Klasse überschreiben. Die einfachste Methode ist die von `Zend_Controller_Front`, welche es an das Request Object weiter leitet. Beispiel, um eine eigene Basis URL zu setzen:

    /**
     * Dispatch Request with custom base URL with Zend_Controller_Front.
     */
    $router     = new Zend_Controller_RewriteRouter();
    $controller = Zend_Controller_Front::getInstance();
    $controller->setControllerDirectory('./application/controllers')
               ->setRouter($router)
               ->setBaseUrl('/projects/myapp'); // set the base url!
    $response   = $controller->dispatch();

### 7.4.3. Zend_Controller_RewriteRouter

#### 7.4.3.1. Einführung

`Zend_Controller_RewriteRouter` ist eine neue Version des Framework Routers. Routing ist der Prozess der Übernahme und Zerteilung einer URI, um zu ermitteln, welcher Controller und welche Aktion des Controllers die Anfrage erhalten soll. Die Definition des Controllers, der Aktion sowie weiterer Parameter wird in einem Objekt mit Namen `Zend_Controller_Dispatcher_Token` gekapselt, das dann vom `Zend_Controller_Dispatcher` verarbeitet wird. Das Routing geschieht nur einmal: wenn zu Beginn die Anfrage erhalten wird und bevor der erste Controller aufgerufen wird.

`Zend_Controller_RewriteRouter` wurde entwickelt, um mit reinen PHP Strukturen eine mod_rewrite ähnliche Funktionalität zu erlauben. Es richtet sich sehr frei nach dem Ruby on Rails Routing und benötigt kein tieferes Wissen über URL Weiterleitung des Webservers. Es wurde entwickelt, um mit einer einzigen mod_rewrite Regel zu arbeiten.

    RewriteEngine on
    RewriteRule !\.(js|ico|gif|jpg|png|css)$ index.php

oder:

    RewriteEngine on
    RewriteCond %{SCRIPT_FILENAME} !-f
    RewriteCond %{SCRIPT_FILENAME} !-d
    RewriteRule ^(.*)$ index.php/$1

Der RewriteRouter kann auch mit dem IIS Webserver verwendet werden, wenn Isapi_Rewrite als Isapi Erweiterung installiert wurde und folgende Umschreibungsregel verwendet wird:

    RewriteRule ^[\w/\%]*(?:\.(?!(?:js|ico|gif|jpg|png|css)$)[\w\%]*$)? /index.php [I]

| IIS Isapi_Rewrite
Bei Verwenung von IIS, wird `$_SERVER['REQUEST_URI']` entweder nicht vorhanden sein oder auf einen leeren String gesetzt sein. In diesem Fall wird `Zend_Controller_Request_Http` versuchen, den durch die Isapi_Rewrite Erweiterung gesetzten Wert `$_SERVER['HTTP_X_REWRITE_URL']` zu verwenden.

Bei der verwendung von Lighttpd, ist folgende Umschreibungsregel gültig:

    url.rewrite-once = ( ".*\.(js|ico|gif|jpg|png|css)$" => "$0", "" => "/index.php")

#### 7.4.3.2. Einen Router verwenden

Um den RewriteRouter richtig zu verwenden, mußt du ihn instanziieren, einige benutzerdefinierte Routen hinzufügen und in den Controller einbinden. Der folgende Code veranschaulicht die Vorgehensweise:

    /* Erstelle einen Router */

    $router = new Zend_Controller_RewriteRouter();
    $router->addRoute(
    	'user',
    	new Zend_Controller_Router_Route('user/:username', array('controller' => 'user', 'action' => 'info'))
    );

    /* binde ihn in den Controller ein */

    $ctrl = Zend_Controller_Front::getInstance();
    $ctrl->setRouter($router);

#### 7.4.3.3. Einfache Routen

Das Herz des RewriteRouter ist die Definition der benutzerdefinierten Routen. Routen werden durch Aufruf der `addRoute` Methode des RewriteRouter und der Übergabe einer neuen Instanz von `Zend_Controller_Router_Route` erstellt:

    $router->addRoute('user', new Zend_Controller_Router_Route('user/:username'));

Der erste Parameter ist der Name der Route. Zum derzeitigen Zeitpunkt ist er redundant aber wird in Zukunft in einem URL View Helper verwendet, um eine einfache Erstellung von URLs in deinen Views zu ermöglichen. Wenn du die vorher konfigurierte, benannte Route verwenden möchtest, kannst du sie mit den `getRoute` Methode des RewriteRouter erhalten. Der zweite Parameter ist eine Instanz von `Zend_Controller_Router_Route`.

The erste Parameter für den `Zend_Controller_Router_Route` Konstruktur ist eine Route, die auf eine URL passt - zum Beispiel passt die obige Route auf `http://example.com/user/martel`. Der Doppelpunkt in einer Route markiert eine URL Variable, die durch die `Zend_Controller_Action::_getParam` Methode zugänglich ist. In unserem Beispiel wird der mit 'username' benannte Parameter auf den Wert 'martel' gesetzt.

| Reihenfolge der Definitionen
Routen werden in umgekehrter Reihenfolge abgeglichen, so dass man sicherstellen muss, dass die allgemeinste Route als erstes definiert ist.

| Erlaubte Zeichen
Fürs Erste erlaubt die aktuelle Implementation die Verwendung jedes Zeichens für den Variablenbezeichner außer den Schrägstrich (/), es wird aber sehr empfohlen, dass du nur Zeichen verwendest, die für PHP Variablen verwendet werden dürfen. In Zukunft wird die Implementation vermutlich angepasst und dies könnte Fehler in deinen Code einführen.

Es gibt zwei besondere Variablen, die in deinen Routen verwendet werden können - 'controller' und 'action'. Diese besonderen Variablen werden verwendet, um einen gewählten Controller und/oder eine Aktion in der URL zu finden. Die 'action' Variable muß immer entweder in der Route oder als Standardparameter definiert sein. Die 'controller' Variable wird standardmäßig auf IndexController verweisen, wenn sie nicht definiert wurde.

| Spezielle Variablen
Die Namen dieser speziellen Variablen können unterschiedlich sein, wenn man die Standardwerte in `Zend_Controller_Request_Http` mit Hilfe der setControllerKey und setActionKey Methoden verändert.

    $router->addRoute(
        'user', new Zend_Controller_Router_Route(':controller/:action')
    );

Wenn du deinen Browser mit dieser Route auf `http://example.com/news/latest` richtest, wird der `Zend_Controller_Dispatcher` die Aktion latestAction deines Controllers NewsController ausführen.

#### 7.4.3.4. Vorgegebene Variablenwerte

Jede Variable in der Route kann einen vorgegebenen Wert haben. Um diesen vorzugeben, mußt du einen dritten Parameter zur `addRoute` Methode hinzufügen. Dieser dritte Parameter ist ein Array mit den Variablennamen als Schlüssel und den vorgegebenen Werten als Werten.

    $router->addRoute(
        'archive', new Zend_Controller_Router_Route('archive/:year', array('year' => 2006))
    );

Was nicht sofort erkennbar sein mag, ist, dass die obige Route auf URLs wie `http://example.com/archive/2005` und `http://example.com/archive` passt. Im letzteren Fall hat die Variable 'year' den Wert 2006.

Im obigen Beispiel haben wir keinen Controller angegeben, so dass immer auf die noRoute Aktion des IndexController verwiesen wird. Damit es anwendbar ist, musst du einen gültigen Controller und eine gültige Aktion als Standardwerte festlegen:

    $router->addRoute(
        'archive',
        new Zend_Controller_Router_Route('archive/:year', array('year' => 2006, 'controller' => 'archive', 'action' => 'show')
    );

This route will then result in dispatching to showAction of ArchiveController.

#### 7.4.3.5. Anforderungen an Variablen

Du kannst einen dritten Parameter hinzufügen, in dem Anforderungen an die Variablen angegeben werden können. Diese werden als reguläre Ausdrücke definiert:

    $router->addRoute(
        'archive',
        new Zend_Controller_Router_Route('archive/:year', array('year' => 2006), array('year' => '\d+'))
    );

| Routing Verhalten
Im Gegensatz zu Ruby on Rails wird `Zend_Controller_RewriteRouter` für eine Route Standardwerte verwenden, wenn die Anforderungen an die Variablen im vierten Parameter nicht erfüllt werden. Also passt die URL `http://example.com/archive/test` auf die obige Route und setzt den Parameter 'year' auf 2006. Diese Funktionalität kann sich in Zukunft ändern, da sie im Moment beim Schreiben dieser Dokumentation noch diskutiert wird.

#### 7.4.3.6. Basis URL und Unterverzeichnisse

Im Gegensatz zum ursprünglichen Route kann RewriteRouter auch in Unterverzeichnissen verwendet werden. Die Methode setRewriteBase() des ursprünglichen RewriteRouter existiert nicht mehr. Stattdessen wird die Basis URL automatisch durch Zend_Controller_Request_Http ermittelt.

Sollte die Basis URL falsch erkannt werden, kannst du sie mit deinem eigenen Pfad mit Hilfe von Zend_Controller_Request_Http durch den Aufruf der setBaseUrl() Methode setzen (siehe Abschnitt 7.4.2.3, „Basis Url und Unterverzeichnisse“).

#### 7.4.3.7. Standardrouten

`Zend_Controller_RewriteRouter` hat eine vordefinierte Standardroute, um Kompatibilität mit der ersten Version des Routers zu gewährleisten. Sie passt auf URIs in Form von `'controller/action'` and erkennt außerdem jeden zusätzlichen Parameter, der an die URI angehängt wird. Sie ist wie folgt konfiguiert:

    // Route for Router v1 compatibility
    $compat = new Zend_Controller_Router_Route(':controller/:action/*', array('controller' => 'index', 'action' => 'index'));
    $this->addRoute('default', $compat);

| URIs abbilden
Zend_Controller_RewriteRouter wurde für Rückwärtskompatibilität konfiguriert. Es passt automatisch auf `controller/action` URIs mit zusätzlichen Parameter. Die zusätzlichen Parameter benötigen keine weiteren Routen, solange sie keine vorgegebenen Variablenwerte oder Variablenanforderungen benötigen. Auf diese zusätzlichen Parameter kann über die Zend_Controller_Action::_getParam() Methode zugegriffen werden.

Wenn man die Standardroute nicht in seinem Routing Schema haben möchte, kann diese mit Hilfe von `removeDefaultRoutes()` entfernt werden:

    // Entferne Standardroute
    $router->removeDefaultRoutes();

#### 7.4.3.8. Statische Routen

Die obigen Beispiele verwenden alle dynamische Routen - Routen die zu prüfende Muster verwenden. Manchmal ist eine bestimmte Route jedoch fest verankert und die Verwendung regulärer Ausdrücke wäre zuviel des Guten. Die Antwort auf solche Situationen ist die Verwendung von statischen Routen:

    $loginRoute = new Zend_Controller_Router_StaticRoute('login', array('controller' => 'login', 'action' => 'form'));
    $router->addRoute('login', $static);

#### 7.4.3.9. Zend_Config mit dem RewriteRouter verwenden

Manchmal ist es praktischer, eine Konfigurationsdatei mit neuen Routen zu aktualisieren, als den Code zu ändern. Dies ist mit Hilfe der `addConfig()` Methode möglich. Im Wesentlichen kann man eine Zend_Config kompatible Konfiguration erstellen, in seinem Code einlesen und an den RewriteRouter übergeben:

    /**
     * Beispiel INI:
     * routes.archive.route = "archive/:year/*"
     * routes.archive.defaults.controller = archive
     * routes.archive.defaults.action = show
     * routes.archive.defaults.year = 2000
     * routes.archive.reqs.year = "\d+"
     *
     * routes.news.type = "Zend_Controller_Router_StaticRoute"
     * routes.news.route = "news"
     * routes.news.defaults.controller = "news"
     * routes.news.defaults.action = "list"
     */
    $config = new Zend_Config_Ini($file);
    $router = new Zend_Controller_RewriteRouter();
    $router->addConfig($config, 'routes');

Im oberen Beispiel teilen wir dem Router mit, den 'routes' Bereich der INI Datei für seine Routen zu verwenden. Jeder Schlüssel auf erster Ebene in diesem Bereich wird verwendet, um den Namen der Routen zu definieren; das obige Beispiel definiert die Routen 'archive' und 'news'. Jede Route erfordert dann mindestens einen 'route' Eintrag und einen oder mehrere 'defaults' Einträge; optional können eine oder mehrere 'reqs' (kurz für 'required', d.h. erforderlich) Einträge angegeben werden. Alles in allem entspricht dies den drei Argumenten, die an ein `Zend_Controller_Router_Route_Interface` Objekt übergeben werden. Ein Optionsschlüssel 'type' kann verwendet werden, um den Typ der Routenklasse für diese Route anzugeben; standardmäßig wird `Zend_Controller_Router_Route` verwendet. Im obigen Beispiel wird die 'news' Route definiert, um `Zend_Controller_Router_StaticRoute` zu verwenden.

#### 7.4.3.10. RewriteRouter mit modularen MVC Komponenten verwenden

Ein RewriteRouter, der Module unterstützt, ist ebenfalls verfügbar: Zend_Controller_ModuleRewriteRouter. Er arbeitet genauso wie Zend_Controller_RewriteRouter, aber hat als Standardroute den Pfad ':module/:controller/:action/*'.

Für weitere Informationen siehe die Abschnitt 7.7, „Using a Conventional Modular Directory Structure“.

### 7.4.4. Zend_Controller_Response_Http

`Zend_Controller_Response_Http` ist ein Response Objekt, das für die Verwendung in einer HTTP Umgebung geeignet ist. Es enthält Methoden für das Setzen, Erhalten und Entfernen von Headern und die `__toString()` Methode sendet alle Header auf einmal bevor die Reponse Inhalte zurückgegeben werden.

`setHeader()` nimmt zwei Argumente entgegen, einen Header Typ und den Header Wert. Ein dritter, optionaler Parameter (wenn übergeben und true) erzwingt das Überschreiben des vorhandenen Headers gleichen Typs mit dem neuen Header.

### 7.4.5. Zend_Controller_Response_Cli

`Zend_Controller_Response_Cli` is ein Response Object, das für die Verwendung in einer CLI Umgebung geeignet ist. Es hat keine Methoden für die Behandlung von Headern und gibt nur alle Inhalte zurück, wenn `__toString()` aufgerufen wird.

Zurück | Nach oben | Weiter
7.3. Klassen ableiten | Zum Anfang | 7.5. Action Controllers