| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- EN-Revision: 15103 -->
- <!-- 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 URI, 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 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.
- </para>
- <programlisting role="php"><![CDATA[
- RewriteEngine on
- RewriteRule !\.(js|ico|gif|jpg|png|css|html)$ index.php
- ]]>
- </programlisting>
- <para>
- oder (bevorzugt):
- </para>
- <programlisting role="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 IIS 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 role="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 IIS, wird <code>$_SERVER['REQUEST_URI']</code> entweder nicht
- vorhanden oder auf einen leeren String gesetzt sein. In diesem Fall wird
- <classname>Zend_Controller_Request_Http</classname> versuchen, den durch die Isapi_Rewrite
- Erweiterung gesetzten Wert <code>$_SERVER['HTTP_X_REWRITE_URL']</code> zu
- verwenden.
- </para>
- </note>
- <para>
- IIS 7.0 führt ein natives URL Rewriting Modul ein, und kann wie folgt konfiguriert werden:
- </para>
- <programlisting role="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 role="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 role="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 role="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><xref linkend="zend.controller.router.routes.standard" /></para></listitem>
- <listitem><para><xref linkend="zend.controller.router.routes.static" /></para></listitem>
- <listitem><para><xref linkend="zend.controller.router.routes.regex" /></para></listitem>
- <listitem><para><xref linkend="zend.controller.router.routes.hostname" /></para></listitem>
- <listitem><para><xref linkend="zend.controller.router.routes.chain" /></para></listitem>
- <listitem><para><xref linkend="zend.controller.router.default-routes" /> *</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 URL 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 role="php"><![CDATA[
- <a href=
- "<?php echo $this->url(array('username' => 'martel'), 'user') ?>">Martel</a>
- ]]>
- </programlisting>
- <para>
- Was zu folgender href führt: <code>user/martel</code>.
- </para>
- </note>
- <para>
- Routen ist ein einfacher Prozess des Durchlaufens aller vorhandenen Routen und Vergleichens deren
- Definitionen mit der aktuellen Anfrage URI. 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 <code>getCurrentRouteName()</code>
- 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
- <code>getCurrentRoute()</code> 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 URL Parametern oder Benutzerdefinierten
- Router Standards. Diese Variablen sind später durch die
- <classname>Zend_Controller_Request::getParam()</classname> oder
- <classname>Zend_Controller_Action::_getParam()</classname>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 Kontroller 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 <code>setControllerKey</code>
- und <code>setActionKey</code> 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 URIs im Sinn
- von <code>controller/action</code> entspricht. Zusätzlich kann ein Modul Name als erstes Pfad Element
- definiert werden, welches URIs in der Form von <code>module/controller/action</code> erlaubt.
- Letztendlich wird es auch allen zusätzlichen Parametern entsprechen die der URI standardmäßig
- hinzugefügt wurden - <code>controller/action/var1/value1/var2/value2</code>.
- </para>
- <para>
- Einige Beispiele wie solche Routen verglichen werden:
- </para>
- <programlisting role="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 role="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 <code>removeDefaultRoutes()</code>:
- </para>
- <programlisting role="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.
- <code>http://domain.com/~user/application-root/</code>) und in diesem Fall sollte die Basis URL der
- Anwendung (<code>/~user/application-root</code>) automatisch durch
- <classname>Zend_Controller_Request_Http</classname> erkannt und auch verwendet werden.
- </para>
- <para>
- Sollte die Basis URL nicht richtig erkannt werden kann diese mit eigenen Basispfad überschrieben werden
- durch Verwendung von <classname>Zend_Controller_Request_Http</classname> und Auruf der <code>setBaseUrl()</code>
- Methode (siehe <xref linkend="zend.controller.request.http.baseurl" />):
- </para>
- <programlisting role="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 <code>setGlobalParam</code> 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 role="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" />
- </sect2>
- <sect2 id="zend.controller.router.add-config">
- <title><classname>Zend_Config</classname> 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
- <code>addConfig()</code> 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 INI Datei angenommen:
- </para>
- <programlisting role="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 INI Datei kann dann wie folgt in ein
- <classname>Zend_Config</classname> Objekt eingelesen werden:
- </para>
- <programlisting role="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 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
- <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 role="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>
- <!--
- vim:se ts=4 sw=4 et:
- -->
|