| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- EN-Revision: 24249 -->
- <!-- Reviewed: no -->
- <sect1 id="zend.controller.router" xmlns:xi="http://www.w3.org/2001/XInclude">
- <title>Der Standard Router</title>
- <sect2 id="zend.controller.router.introduction">
- <title>Einführung</title>
- <para>
- <classname>Zend_Controller_Router_Rewrite</classname> ist der Standard Router des
- Frameworks. Routing ist der Prozess der Übernahme und Zerteilung einer
- <acronym>URI</acronym> (dem Teil der <acronym>URI</acronym> der nach der Basis
- <acronym>URL</acronym> kommt), um zu ermitteln, welches Modul, welcher Controller und
- welche Aktion des Controllers die Anfrage erhalten soll. Die Definition des Moduls, des
- Controllers, der Aktion sowie weiterer Parameter wird in einem Objekt mit Namen
- <classname>Zend_Controller_Dispatcher_Token</classname> gekapselt, das dann vom
- <classname>Zend_Controller_Dispatcher_Standard</classname> verarbeitet wird. Das Routing
- geschieht nur einmal: wenn zu Beginn die Anfrage erhalten wird und bevor der erste
- Controller aufgerufen wird.
- </para>
- <para>
- <classname>Zend_Controller_Router_Rewrite</classname> wurde entwickelt, um mit reinen
- <acronym>PHP</acronym> 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 <acronym>URL</acronym> Weiterleitung des Webservers. Es wurde entwickelt, um
- mit einer einzigen mod_rewrite Regel zu arbeiten.
- </para>
- <programlisting language="php"><![CDATA[
- RewriteEngine on
- RewriteRule !\.(js|ico|gif|jpg|png|css|html)$ index.php
- ]]></programlisting>
- <para>
- oder (bevorzugt):
- </para>
- <programlisting language="php"><![CDATA[
- RewriteEngine On
- RewriteCond %{REQUEST_FILENAME} -s [OR]
- RewriteCond %{REQUEST_FILENAME} -l [OR]
- RewriteCond %{REQUEST_FILENAME} -d
- RewriteRule ^.*$ - [NC,L]
- RewriteRule ^.*$ index.php [NC,L]
- ]]></programlisting>
- <para>
- Der Rewrite Router kann auch mit dem <acronym>IIS</acronym> Webserver verwendet werden
- (Versionen <= 7.0), wenn <ulink
- url="http://www.isapirewrite.com">Isapi_Rewrite</ulink> als Isapi
- Erweiterung installiert wurde und folgende Umschreibungsregel verwendet wird:
- </para>
- <programlisting language="php"><![CDATA[
- RewriteRule ^[\w/\%]*(?:\.(?!(?:js|ico|gif|jpg|png|css|html)$)[\w\%]*$)? /index.php [I]
- ]]></programlisting>
- <note>
- <title>IIS Isapi_Rewrite</title>
- <para>
- Bei Verwendung von <acronym>IIS</acronym>, wird
- <varname>$_SERVER['REQUEST_URI']</varname> entweder nicht vorhanden oder auf einen
- leeren String gesetzt sein. In diesem Fall wird
- <classname>Zend_Controller_Request_Http</classname> versuchen, den durch die
- <classname>Isapi_Rewrite</classname> Erweiterung gesetzten Wert
- <varname>$_SERVER['HTTP_X_REWRITE_URL']</varname> zu verwenden.
- </para>
- </note>
- <para>
- <acronym>IIS</acronym> 7.0 führt ein natives <acronym>URL</acronym> Rewriting Modul
- ein, und kann wie folgt konfiguriert werden:
- </para>
- <programlisting language="xml"><![CDATA[
- <?xml version="1.0" encoding="UTF-8"?>
- <configuration>
- <system.webServer>
- <rewrite>
- <rules>
- <rule name="Imported Rule 1" stopProcessing="true">
- <match url="^.*$" />
- <conditions logicalGrouping="MatchAny">
- <add input="{REQUEST_FILENAME}"
- matchType="IsFile" pattern=""
- ignoreCase="false" />
- <add input="{REQUEST_FILENAME}"
- matchType="IsDirectory"
- pattern="" ignoreCase="false" />
- </conditions>
- <action type="None" />
- </rule>
- <rule name="Imported Rule 2" stopProcessing="true">
- <match url="^.*$" />
- <action type="Rewrite" url="index.php" />
- </rule>
- </rules>
- </rewrite>
- </system.webServer>
- </configuration>
- ]]></programlisting>
- <para>
- Bei der Verwendung von Lighttpd, ist folgende Umschreibungsregel gültig:
- </para>
- <programlisting language="lighttpd"><![CDATA[
- url.rewrite-once = (
- ".*\?(.*)$" => "/index.php?$1",
- ".*\.(js|ico|gif|jpg|png|css|html)$" => "$0",
- "" => "/index.php"
- )
- ]]></programlisting>
- </sect2>
- <sect2 id="zend.controller.router.usage">
- <title>Einen Router verwenden</title>
- <para>
- Um den Rewrite Router richtig zu verwenden, muß er instanziiert, einige
- benutzerdefinierte Routen hinzufügt und in den Controller einbunden werden. Der folgende
- Code veranschaulicht die Vorgehensweise:
- </para>
- <programlisting language="php"><![CDATA[
- // Einen Router erstellen
- $router = $ctrl->getRouter(); // gibt standardmäßig einen Rewrite Router zurück
- $router->addRoute(
- 'user',
- new Zend_Controller_Router_Route('user/:username',
- array('controller' => 'user',
- 'action' => 'info'))
- );
- ]]></programlisting>
- </sect2>
- <sect2 id="zend.controller.router.basic">
- <title>Grundsätzliche Rewrite Router Operationen</title>
- <para>
- Das Herz des RewriteRouters ist die Definition von Benutzerdefinierten Routen. Routen
- werden durch aufruf der addRoute Methode des RewriteRouters hinzugefügt und übergeben
- eine neue Instanz einer Klasse die
- <classname>Zend_Controller_Router_Route_Interface</classname> implementiert. Z.B.:
- </para>
- <programlisting language="php"><![CDATA[
- $router->addRoute('user',
- new Zend_Controller_Router_Route('user/:username'));
- ]]></programlisting>
- <para>
- Der Rewrite Router kommt mit sechs Basistypen von Routen (eine von denen ist speziell):
- is special):
- </para>
- <itemizedlist mark="opencircle">
- <listitem>
- <para>
- <link
- linkend="zend.controller.router.routes.standard">Zend_Controller_Router_Route</link>
- </para>
- </listitem>
- <listitem>
- <para>
- <link
- linkend="zend.controller.router.routes.static">Zend_Controller_Router_Route_Static</link>
- </para>
- </listitem>
- <listitem>
- <para>
- <link
- linkend="zend.controller.router.routes.regex">Zend_Controller_Router_Route_Regex</link>
- </para>
- </listitem>
- <listitem>
- <para>
- <link
- linkend="zend.controller.router.routes.hostname">Zend_Controller_Router_Route_Hostname</link>
- </para>
- </listitem>
- <listitem>
- <para>
- <link
- linkend="zend.controller.router.routes.chain">Zend_Controller_Router_Route_Chain</link>
- </para>
- </listitem>
- <listitem>
- <para>
- <link
- linkend="zend.controller.router.default-routes">Zend_Controller_Router_Rewrite</link>
- *
- </para>
- </listitem>
- </itemizedlist>
- <para>
- Routen können unzählige Male verwendet werden um eine Kette oder benutzerdefinierte
- Routing Schemas von Anwendungen zu erstellen. Es kann jede beliebige Anzahl von Routen
- in jeder beliebigen Konfiguration verwendet werden, mit Ausnahme der Modul Route, welche
- nur einmal verwendet werden sollte, und möglicherweise die am meisten standardmäßige
- Route ist (z.B., als ein Standard). Jede Route wird später detailiert beschrieben.
- </para>
- <para>
- Der erste Parameter für addRoute ist der Name der Route. Er wird als Handle verwendet um
- die Route außerhalb des Routers zu erhalten (z.B. für den Zweck der
- <acronym>URL</acronym> Erzeugung). Der zweite Parameter ist die Route selbst.
- </para>
- <note>
- <para>
- Die gewöhnlichste Verwendung des Namens der Route ist gegeben durch die Zwecke des
- <classname>Zend_View</classname> Url Helfers:
- </para>
- <programlisting language="php"><![CDATA[
- <a href=
- "<?php echo $this->url(array('username' => 'martel'), 'user') ?>">Martel</a>
- ]]></programlisting>
- <para>
- Was zu folgender href führt: <filename>user/martel</filename>.
- </para>
- </note>
- <para>
- Routen ist ein einfacher Prozess des Durchlaufens aller vorhandenen Routen und
- Vergleichens deren Definitionen mit der aktuellen Anfrage <acronym>URI</acronym>. Wenn
- ein positiver Vergleich gefunden wird, werden variable Werte von der Instanz des Routers
- zurückgegeben, und werden für die spätere Verwendung im Dispatcher in das
- <classname>Zend_Controller_Request</classname> Objekt iniziiert, sowie in von Benutzern
- erstellten Controllern. Bei einem negativen Ergebnis des Vergleiches, wird die nächste
- Route in der Kette geprüft.
- </para>
- <para>
- Wenn man herausfinden will welche Route gepasst hat, kann man die
- <methodname>getCurrentRouteName()</methodname> Methode verwenden, die den Identifikator
- zurückgibt der verwendet wurde als die Route im Router registriert wurde. Wenn man das
- aktuelle Route Objekt benötigt, kann <methodname>getCurrentRoute()</methodname>
- verwendet werden.
- </para>
- <note>
- <title>Umgekehrter Vergleich</title>
- <para>
- Routen werden in umgekehrter Reihenfolge verglichen. Deswegen muß sichergestellt
- werden das die generellen Routen zuerst definiert werden.
- </para>
- </note>
- <note>
- <title>Zurückgegebene Werte</title>
- <para>
- Werte die vom Routen zurückgegeben werden kommen von <acronym>URL</acronym>
- Parametern oder Benutzerdefinierten Router Standards. Diese Variablen sind später
- durch die <methodname>Zend_Controller_Request::getParam()</methodname> oder
- <methodname>Zend_Controller_Action::_getParam()</methodname>Methoden verwendbar.
- </para>
- </note>
- <para>
- Es gibt drei spezielle Variablen welche in den Routen verwendet werden können -
- 'module', 'controller' und 'action'. Diese speziellen Variablen werden durch
- <classname>Zend_Controller_Dispatcher</classname> verwendet um einen Controller und die
- Aktion zu funden zu der verwiesen wird.
- </para>
- <note>
- <title>Spezielle Variablen</title>
- <para>
- Die Namen dieser speziellen Variablen kann unterschiedlich sein wenn entschieden
- wird die Standards in <classname>Zend_Controller_Request_Http</classname> mithilfe
- der <methodname>setControllerKey()</methodname> und
- <methodname>setActionKey()</methodname> Methode zu Ändern.
- </para>
- </note>
- </sect2>
- <sect2 id="zend.controller.router.default-routes">
- <title>Standard Routen</title>
- <para>
- <classname>Zend_Controller_Router_Rewrite</classname> kommt mit einer Standard Route
- vorkonfiguriert, welche <acronym>URI</acronym>s im Sinn von
- <filename>controller/action</filename> entspricht. Zusätzlich kann ein Modul Name als
- erstes Pfad Element definiert werden, welches <acronym>URI</acronym>s in der Form von
- <filename>module/controller/action</filename> erlaubt. Letztendlich wird es auch allen
- zusätzlichen Parametern entsprechen die der <acronym>URI</acronym> standardmäßig
- hinzugefügt wurden - <filename>controller/action/var1/value1/var2/value2</filename>.
- </para>
- <para>
- Einige Beispiele wie solche Routen verglichen werden:
- </para>
- <programlisting language="php"><![CDATA[
- // Folgende Annahme:
- $ctrl->setControllerDirectory(
- array(
- 'default' => '/path/to/default/controllers',
- 'news' => '/path/to/news/controllers',
- 'blog' => '/path/to/blog/controllers'
- )
- );
- Nur Modul:
- http://example/news
- module == news
- Ungültiges Modul, geht an den Controller Namen:
- http://example/foo
- controller == foo
- Modul + Controller:
- http://example/blog/archive
- module == blog
- controller == archive
- Modul + Controller + Aktion:
- http://example/blog/archive/list
- module == blog
- controller == archive
- action == list
- Modul + Controller + Aktion + Parameter:
- http://example/blog/archive/list/sort/alpha/date/desc
- module == blog
- controller == archive
- action == list
- sort == alpha
- date == desc
- ]]></programlisting>
- <para>
- Die Standardroute ist einfach ein
- <classname>Zend_Controller_Router_Route_Module</classname> Objekt welches unter dem
- Namen (Index) 'default' im RewriteRouter gespeichert ist. Es wird mehr oder weniger wie
- folgt erstellt:
- </para>
- <programlisting language="php"><![CDATA[
- $compat = new Zend_Controller_Router_Route_Module(array(),
- $dispatcher,
- $request);
- $this->addRoute('default', $compat);
- ]]></programlisting>
- <para>
- Wenn diese spezielle Standard Route im eigenen Routing Schema nicht gewünscht ist, kann
- Sie durch Erstellung einer eigenen 'default' Route überschrieben werden (z.B. durch
- Speichern unter dem Namen 'default') oder dem kompletten Entfernen durch verwenden von
- <methodname>removeDefaultRoutes()</methodname>:
- </para>
- <programlisting language="php"><![CDATA[
- // Löschen aller Standard Routen
- $router->removeDefaultRoutes();
- ]]></programlisting>
- </sect2>
- <sect2 id="zend.controller.router.rewritebase">
- <title>Basis URL und Unterverzeichnisse</title>
- <para>
- Der Rewrite Router kann in Unterverzeichnissen verwendet werden (z.B.
- <filename>http://domain.com/user/application-root/</filename>) und in diesem Fall
- sollte die Basis <acronym>URL</acronym> der Anwendung
- (<filename>/user/application-root</filename>) automatisch durch
- <classname>Zend_Controller_Request_Http</classname> erkannt und auch verwendet werden.
- </para>
- <para>
- Sollte die Basis <acronym>URL</acronym> nicht richtig erkannt werden kann diese mit
- eigenen Basispfad überschrieben werden durch Verwendung von
- <classname>Zend_Controller_Request_Http</classname> und Auruf der
- <methodname>setBaseUrl()</methodname> Methode (siehe <link
- linkend="zend.controller.request.http.baseurl">Basis URL und
- Unterverzeichnisse</link>):
- </para>
- <programlisting language="php"><![CDATA[
- $request->setBaseUrl('/~user/application-root/');
- ]]></programlisting>
- </sect2>
- <sect2 id="zend.controller.router.global.parameters">
- <title>Globale Parameter</title>
- <para>
- Man kann in einem Router globale Parameter setzen die der Route automatisch zur
- Verfügung stehen wenn Sie durch <methodname>setGlobalParam()</methodname> eingefügt
- werden. Wenn ein globaler Parameter gesetzt ist, aber auch direkt an die Assemble
- Methode gegeben wird, überschreibt der Benutzer-Parameter den Globalen-Parameter.
- Globale Parameter können auf folgendem Weg gesetzt werden:
- </para>
- <programlisting language="php"><![CDATA[
- $router->setGlobalParam('lang', 'en');
- ]]></programlisting>
- </sect2>
- <sect2 id="zend.controller.router.routes">
- <title>Router Typen</title>
- <xi:include href="Zend_Controller-Router-Route.xml" />
- <xi:include href="Zend_Controller-Router-Route-Static.xml" />
- <xi:include href="Zend_Controller-Router-Route-Regex.xml" />
- <xi:include href="Zend_Controller-Router-Route-Hostname.xml" />
- <xi:include href="Zend_Controller-Router-Route-Chain.xml" />
- <xi:include href="Zend_Controller-Router-Route-Rest.xml" />
- </sect2>
- <sect2 id="zend.controller.router.add-config">
- <title>Zend_Config mit dem RewriteRouter verwenden</title>
- <para>
- Manchmal ist es praktischer, eine Konfigurationsdatei mit neuen Routen zu
- aktualisieren, als den Code zu ändern. Dies ist mit Hilfe der
- <methodname>addConfig()</methodname> Methode möglich. Im Wesentlichen kann man eine
- <classname>Zend_Config</classname> kompatible Konfiguration erstellen, in seinem Code
- einlesen und an den RewriteRouter übergeben:
- </para>
- <para>
- Als Beispiel wird die folgende <acronym>INI</acronym> Datei angenommen:
- </para>
- <programlisting language="php"><![CDATA[
- [production]
- 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_Route_Static"
- routes.news.route = "news"
- routes.news.defaults.controller = "news"
- routes.news.defaults.action = "list"
- routes.archive.type = "Zend_Controller_Router_Route_Regex"
- routes.archive.route = "archive/(\d+)"
- routes.archive.defaults.controller = "archive"
- routes.archive.defaults.action = "show"
- routes.archive.map.1 = "year"
- ; OR: routes.archive.map.year = 1
- ]]></programlisting>
- <para>
- Die oben angeführte <acronym>INI</acronym> Datei kann dann wie folgt in ein
- <classname>Zend_Config</classname> Objekt eingelesen werden:
- </para>
- <programlisting language="php"><![CDATA[
- $config = new Zend_Config_Ini('/path/to/config.ini', 'production');
- $router = new Zend_Controller_Router_Rewrite();
- $router->addConfig($config, 'routes');
- ]]></programlisting>
- <para>
- Im oberen Beispiel teilen wir dem Router mit, den 'routes' Bereich der
- <acronym>INI</acronym> 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
- <classname>Zend_Controller_Router_Route_Interface</classname> Objekt übergeben werden.
- Ein Optionsschlüssel 'type' kann verwendet werden, um den Typ der Routenklasse für
- diese Route anzugeben; standardmäßig wird
- <classname>Zend_Controller_Router_Route</classname> verwendet. Im obigen Beispiel wird
- die 'news' Route definiert, um
- <classname>Zend_Controller_Router_Route_Static</classname> zu verwenden.
- </para>
- </sect2>
- <sect2 id="zend.controller.router.subclassing">
- <title>Erben vom Router</title>
- <para>
- Der Standard Rewrite Router sollte die meisten Funktionalitäten die benötigt werden zur
- Verfügung stellen; meistens wird es nur notwendig sein einen neuen Router Typen zu
- erstellen um neue oder modifizierte Funktionalitäten für die verfügbaren Routen zu
- bieten.
- </para>
- <para>
- So gesehen, wird man in einigen Fällen ein anderes Routing Paradigma verwenden wollen.
- Das Interface <classname>Zend_Controller_Router_Interface</classname> bietet die
- minimalen Information die benötigt werden um einen Router er erstellen und besteht aus
- einer einzigen Methode.
- </para>
- <programlisting language="php"><![CDATA[
- interface Zend_Controller_Router_Interface
- {
- /**
- * @param Zend_Controller_Request_Abstract $request
- * @throws Zend_Controller_Router_Exception
- * @return Zend_Controller_Request_Abstract
- */
- public function route(Zend_Controller_Request_Abstract $request);
- }
- ]]></programlisting>
- <para>
- Das Routing findet nur einmal statt, wenn die Anfrage das erste Mal vom System erhalten
- wird. Der Zweck des Routers ist es, Controller, Aktion und optionale Parameter auf Basis
- der Anfrageumgebung zu ermitteln und im Request zu setzen. Das Request Objekt wird dann
- an den Dispatcher übergeben. Wenn es nicht möglich ist, eine Route auf einen Dispatch
- Token abzubilden, soll der Router nichts mit dem Request Objekt machen.
- </para>
- </sect2>
- </sect1>
|