4.3. Subclassing
Zurück | Kapitel 4. Zend_Controller | Weiter

## 4.3. Subclassing

### 4.3.1. Einführung

Das `Zend_Controller` System wurde im Sinne der Erweiterungsmöglichkeiten entwickelt, entweder durch Erstellen von Subklassen, welche die bestehenden Klassen erweitern, oder durch Erstellen neuer Klassen, welche die Interfaces `Zend_Controller_Router_Interface` und `Zend_Controller_Dispatcher_Interface` implementieren.

Mögliche Gründe für die Implementierung eines neuen Routers oder Dispatchers könnten sein:

- Das vorhandene System zum URI Routing ist nicht verwendbar, wenn es in eine bestehende Website integriert werden soll, die eigene Konventionen für das Routing verwendet, die nicht mit dem vom Zend Framework bereit gestellten Routing Mechanismus übereinstimmen.

- Du benötigt das Routing für etwas völlig anderes. Die `Zend_Controller_Router` Klasse arbeitet nur mit URIs. Es ist möglich und wahrscheinlich, dass Du das MVC Entwurfsmuster für die Entwicklung eines anderen Programmtyps verwenden möchtest, z.B. für eine Konsolenanwendung. Im Fall einer Konsolenanwendung könnte ein maßgeschneiderter Router die Kommandozeilenparameter für das Routing verwenden.

- Der vom `Zend_Controller_Dispatcher` bereitgestellte Mechanismus ist nicht verwendbar. Die vorgegebene Konfiguration setzt die Konvention voraus, dass Controller Klassen und Aktionen die Methoden dieser Klassen sind. Allerdings gibt es hierfür auch viele andere Strategien. Ein Beispiel wäre, dass Controller Verzeichnisse und Aktionen Dateien in diesen Verzeichnissen sind.

- Du möchtest zusätzliche Möglichkeiten bereitstellen, die von allen Controllern geerbt werden sollen. Zum Beispiel wird `Zend_View` standardmäßig nicht von `Zend_Controller_Action` integriert. Stattdessen könntest Du deinen eigenen Controller hierfür erweitern und durch die Verwendung müssen die bereitgestellten `Zend_Controller_Router` oder `Zend_Controller_Dispatcher` nicht geändert werden.

Bitte sei vorsichtig beim Überschreiben wesentlicher Teile des System, besonders beim Dispatcher! Einer der Vorteile des `Zend_Controller` ist, dass er einfache Konventionen für den Aufbau von Applikationen einführt. Wenn zuviel dieses vorgegebenen Verhaltens geändert wird, gehen einige dieser Vorteile verloren. Allerdings gibt es viele verschiedene Anforderungen und eine Lösung kann nicht alle erfüllen. Deshalb wird die Freiheit geboten, wenn sie benötigt wird.

### 4.3.2. Konventionen

Beim Erweitern von Zend_Controller Klassen befolge bitte diese Konventionen für das Bezeichnen und Ablegen von Dateien. Dadurch wird sichergestellt, dass andere Programmierer, die mit dem Zend Framework vertraut sind, dein Projekt leichter verstehen können.

#### 4.3.2.1. Präfix

Klassen, die im Zend Framework enthalten sind, befolgen die Konvention, dass jeder Klasse ein "Zend_" vorangestellt wird. Dies ist der Präfix. Wir empfehlen, dass Du alle deine Klassen in ähnlicher Weise bezeichnest. Wenn dein Firmennamen z.B. Widget, Inc. ist, könnte das Präfix "Widget_" heißen.

#### 4.3.2.2. Verzeichnisstruktur

Die `Zend_Controller` Klassen sind im Bibliotheksverzeichnis wie folgt abgelegt::

    /library
      /Zend
        /Controller
          Action.php
          Dispatcher.php
          Router.php

Wenn du die `Zend_Controller` erweiterst, wird empfohlen, dass die neuen Klassen in der gleichen Struktur unterhalb deines Präfix abgelegt werde. Dies macht es einfacher, sie zu finden, wenn sich jemand in dem Lernprozess befindet, bei dem er sich einen Überblick über dein Projekt beschafft.

Zum Beispiel könnte ein Projekt von Widget, Inc., das nur einen kundenspezifischen Router implementiert, so aussehen:

    /library
      /Zend
      /Widget
        /Controller
          Router.php
          README.txt

Beachte an diesem Beispiel, dass das `Widget/Controller/` Verzeichnis das `Zend/Controller/` Verzeichnis widerspiegelt, wo immer es möglich ist. In diesem Fall wird die Klasse `Widget_Controller_Router` bereitgestellt, die entweder eine Subklasse für `Zend_Controller_Router` oder ein Ersatz ist, bei dem `Zend_Controller_Router_Interface` implementiert wird.

Beachte außerdem, dass in dem obigen Beispiel eine `README.txt` Datei im `Widget/Controller/` Verzeichnis abgelegt worden ist. Zend möchte dich ermuntern, deine Projekte durch Bereitstellung von separaten Tests und Dokumentation für Kunden zu dokumentieren. Wir empfehlen dir, eine einfache `README.txt` Datei genau in diesem Verzeichnis zu platzieren, um kurz deine Änderungen und deren Funktionsweise zu erklären.

### 4.3.3. Router Interface

Das Interface `Zend_Controller_Router_Interface` stellt die Definition für eine einzige Methode bereit:

    <?php

      /**
       * @param  Zend_Controller_Dispatcher_Interface
       * @throws Zend_Controller_Router_Exception
       * @return Zend_Controller_Dispatcher_Token|boolean
       */
      public function route(Zend_Controller_Dispatcher_Interface $dispatcher);

    ?>

Das Routing findet nur einmal statt, wenn die Anfrage das erste Mal vom System erhalten wird. Der Zweck des Routers ist es, einen `Zend_Controller_Dispatch_Token` zu generieren, der den aufzurufenden Controller und die Aktion dieses Controllers angibt. Dieser Token wird dann an den Dispatcher übergeben. Wenn es nicht möglich ist, die Route in einem Token abzubilden (unsinnige Route), sollte der boolesche Wert `FALSE` zurückgegeben werden.

Einige Router können dynamische Elemente verarbeiten und benötigen ein Verfahren, um zu ermitteln, ob der erstellte Token überhaupt ausführbar ist, bevor sie ihn zurückgeben. Aus diesem Grund erhält der Router vom Dispatcher als einziges Argument an seine `route()` Methode einen Objekt-Handle. Um dies zu testen, stellt der Dispatcher eine Methode `isDispatchable()` bereit.

### 4.3.4. Dispatcher Interface

`Zend_Controller_Front` ruft zuerst den Router auf, um den ersten Dispatch Token zu erhalten, den er wiederum an den Dispatcher weiterleitet. Der Dispatcher führt die Aktion aus (instanziiert den Controller und ruft die Aktion auf) und gibt dann entweder den booleschen Wert `FALSE` oder einen neuen Dispatch Token zurück.

`Zend_Controller_Front` ruft wiederholt den Dispatcher auf, bis kein Dispatch Token mehr zürückgegeben wird. Dies nennt sich die Dispatcher Schleife. Sie erlaubt, dass Aktionen sequentiell abgearbeitet werden können, bis alle Arbeiten erledigt sind.

Das Interface `Zend_Controller_Dispatcher_Interface` stellt Definitionen für zwei Methoden bereit:

    <?php

    /**
     * @param  Zend_Controller_Dispatcher_Token $route
     * @return boolean
     */
    public function isDispatchable(Zend_Controller_Dispatcher_Token $route);

    ?>

`isDispatchable()` prüft, ob ein Dispatcher Token ausführbar ist. Falls ja, wird `TRUE` zurückgegeben, andernfalls wird `FALSE` zurückgegeben. Die Definition, was ausführbar ist, bleibt der Klasse vorbehalten, die das Interface implementiert. Im Falle des vorgegebenen Implementation vom `Zend_Controller_Dispatcher` bedeutet dies, dass die Controller Datei existiert, die Klasse in der Datei vorhanden ist und die Aktionsmethode innerhalb dieser Klasse vorhanden ist.

    <?php

    /**
     * @param  Zend_Controller_Dispatcher_Token $route
     * @return Zend_Controller_Dispatcher_Token|boolean
     */
    public function dispatch(Zend_Controller_Dispatcher_Token $route);

    ?>

In `dispatch()` wird die Arbeit erledigt. Diese Methode muß die Aktion des Controllers ausführen. Sie muss entweder einen Dispatch Token oder den den booleschen Wert `FALSE` zurückgeben, um aufzuzeigen, dass keine weitere Arbeit zu erledigen ist.

Zurück | Nach oben | Weiter
4.2. Erste Schritte | Zum Anfang | 4.4. Plugins