Zend_Controller-Router.xml 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- EN-Revision: 17166 -->
  3. <!-- Reviewed: no -->
  4. <sect1 id="zend.controller.router" xmlns:xi="http://www.w3.org/2001/XInclude">
  5. <title>Der Standard Router</title>
  6. <sect2 id="zend.controller.router.introduction">
  7. <title>Einführung</title>
  8. <para>
  9. <classname>Zend_Controller_Router_Rewrite</classname> ist der Standard Router des
  10. Frameworks. Routing ist der Prozess der Übernahme und Zerteilung einer URI, um zu
  11. ermitteln, welches Modul, welcher Controller und welche Aktion des Controllers die
  12. Anfrage erhalten soll. Die Definition des Moduls, des Controllers, der Aktion sowie
  13. weiterer Parameter wird in einem Objekt mit Namen
  14. <classname>Zend_Controller_Dispatcher_Token</classname> gekapselt, das dann vom
  15. <classname>Zend_Controller_Dispatcher_Standard</classname> verarbeitet wird. Das Routing
  16. geschieht nur einmal: wenn zu Beginn die Anfrage erhalten wird und bevor der erste
  17. Controller aufgerufen wird.
  18. </para>
  19. <para>
  20. <classname>Zend_Controller_Router_Rewrite</classname> wurde entwickelt, um mit reinen
  21. PHP Strukturen eine mod_rewrite ähnliche Funktionalität zu erlauben. Es richtet sich
  22. sehr frei nach dem Ruby on Rails Routing und benötigt kein tieferes Wissen über
  23. URL Weiterleitung des Webservers. Es wurde entwickelt, um mit einer einzigen
  24. mod_rewrite Regel zu arbeiten.
  25. </para>
  26. <programlisting language="php"><![CDATA[
  27. RewriteEngine on
  28. RewriteRule !\.(js|ico|gif|jpg|png|css|html)$ index.php
  29. ]]></programlisting>
  30. <para>
  31. oder (bevorzugt):
  32. </para>
  33. <programlisting language="php"><![CDATA[
  34. RewriteEngine On
  35. RewriteCond %{REQUEST_FILENAME} -s [OR]
  36. RewriteCond %{REQUEST_FILENAME} -l [OR]
  37. RewriteCond %{REQUEST_FILENAME} -d
  38. RewriteRule ^.*$ - [NC,L]
  39. RewriteRule ^.*$ index.php [NC,L]
  40. ]]></programlisting>
  41. <para>
  42. Der Rewrite Router kann auch mit dem IIS Webserver verwendet werden (Versionen &lt;=
  43. 7.0), wenn <ulink url="http://www.isapirewrite.com">Isapi_Rewrite</ulink> als Isapi
  44. Erweiterung installiert wurde und folgende Umschreibungsregel verwendet wird:
  45. </para>
  46. <programlisting language="php"><![CDATA[
  47. RewriteRule ^[\w/\%]*(?:\.(?!(?:js|ico|gif|jpg|png|css|html)$)[\w\%]*$)? /index.php [I]
  48. ]]></programlisting>
  49. <note>
  50. <title>IIS Isapi_Rewrite</title>
  51. <para>
  52. Bei Verwendung von IIS, wird <varname>$_SERVER['REQUEST_URI']</varname> entweder
  53. nicht vorhanden oder auf einen leeren String gesetzt sein. In diesem Fall wird
  54. <classname>Zend_Controller_Request_Http</classname> versuchen, den durch die
  55. Isapi_Rewrite Erweiterung gesetzten Wert
  56. <varname>$_SERVER['HTTP_X_REWRITE_URL']</varname> zu verwenden.
  57. </para>
  58. </note>
  59. <para>
  60. IIS 7.0 führt ein natives URL Rewriting Modul ein, und kann wie folgt konfiguriert
  61. werden:
  62. </para>
  63. <programlisting language="xml"><![CDATA[
  64. <?xml version="1.0" encoding="UTF-8"?>
  65. <configuration>
  66. <system.webServer>
  67. <rewrite>
  68. <rules>
  69. <rule name="Imported Rule 1" stopProcessing="true">
  70. <match url="^.*$" />
  71. <conditions logicalGrouping="MatchAny">
  72. <add input="{REQUEST_FILENAME}"
  73. matchType="IsFile" pattern=""
  74. ignoreCase="false" />
  75. <add input="{REQUEST_FILENAME}"
  76. matchType="IsDirectory"
  77. pattern="" ignoreCase="false" />
  78. </conditions>
  79. <action type="None" />
  80. </rule>
  81. <rule name="Imported Rule 2" stopProcessing="true">
  82. <match url="^.*$" />
  83. <action type="Rewrite" url="index.php" />
  84. </rule>
  85. </rules>
  86. </rewrite>
  87. </system.webServer>
  88. </configuration>
  89. ]]></programlisting>
  90. <para>
  91. Bei der Verwendung von Lighttpd, ist folgende Umschreibungsregel gültig:
  92. </para>
  93. <programlisting language="lighttpd"><![CDATA[
  94. url.rewrite-once = (
  95. ".*\?(.*)$" => "/index.php?$1",
  96. ".*\.(js|ico|gif|jpg|png|css|html)$" => "$0",
  97. "" => "/index.php"
  98. )
  99. ]]></programlisting>
  100. </sect2>
  101. <sect2 id="zend.controller.router.usage">
  102. <title>Einen Router verwenden</title>
  103. <para>
  104. Um den Rewrite Router richtig zu verwenden, muß er instanziiert, einige
  105. benutzerdefinierte Routen hinzufügt und in den Controller einbunden werden. Der folgende
  106. Code veranschaulicht die Vorgehensweise:
  107. </para>
  108. <programlisting language="php"><![CDATA[
  109. // Einen Router erstellen
  110. $router = $ctrl->getRouter(); // gibt standardmäßig einen Rewrite Router zurück
  111. $router->addRoute(
  112. 'user',
  113. new Zend_Controller_Router_Route('user/:username',
  114. array('controller' => 'user',
  115. 'action' => 'info'))
  116. );
  117. ]]></programlisting>
  118. </sect2>
  119. <sect2 id="zend.controller.router.basic">
  120. <title>Grundsätzliche Rewrite Router Operationen</title>
  121. <para>
  122. Das Herz des RewriteRouters ist die Definition von Benutzerdefinierten Routen. Routen
  123. werden durch aufruf der addRoute Methode des RewriteRouters hinzugefügt und übergeben
  124. eine neue Instanz einer Klasse die
  125. <classname>Zend_Controller_Router_Route_Interface</classname> implementiert. Z.B.:
  126. </para>
  127. <programlisting language="php"><![CDATA[
  128. $router->addRoute('user',
  129. new Zend_Controller_Router_Route('user/:username'));
  130. ]]></programlisting>
  131. <para>
  132. Der Rewrite Router kommt mit sechs Basistypen von Routen (eine von denen ist speziell):
  133. is special):
  134. </para>
  135. <itemizedlist mark="opencircle">
  136. <listitem>
  137. <para><xref linkend="zend.controller.router.routes.standard" /></para>
  138. </listitem>
  139. <listitem>
  140. <para><xref linkend="zend.controller.router.routes.static" /></para>
  141. </listitem>
  142. <listitem>
  143. <para><xref linkend="zend.controller.router.routes.regex" /></para>
  144. </listitem>
  145. <listitem>
  146. <para><xref linkend="zend.controller.router.routes.hostname" /></para>
  147. </listitem>
  148. <listitem>
  149. <para><xref linkend="zend.controller.router.routes.chain" /></para>
  150. </listitem>
  151. <listitem>
  152. <para><xref linkend="zend.controller.router.default-routes" /> *</para>
  153. </listitem>
  154. </itemizedlist>
  155. <para>
  156. Routen können unzählige Male verwendet werden um eine Kette oder benutzerdefinierte
  157. Routing Schemas von Anwendungen zu erstellen. Es kann jede beliebige Anzahl von Routen
  158. in jeder beliebigen Konfiguration verwendet werden, mit Ausnahme der Modul Route, welche
  159. nur einmal verwendet werden sollte, und möglicherweise die am meisten standardmäßige
  160. Route ist (z.B., als ein Standard). Jede Route wird später detailiert beschrieben.
  161. </para>
  162. <para>
  163. Der erste Parameter für addRoute ist der Name der Route. Er wird als Handle verwendet um
  164. die Route außerhalb des Routers zu erhalten (z.B. für den Zweck der URL Erzeugung). Der
  165. zweite Parameter ist die Route selbst.
  166. </para>
  167. <note>
  168. <para>
  169. Die gewöhnlichste Verwendung des Namens der Route ist gegeben durch die Zwecke des
  170. <classname>Zend_View</classname> Url Helfers:
  171. </para>
  172. <programlisting language="php"><![CDATA[
  173. <a href=
  174. "<?php echo $this->url(array('username' => 'martel'), 'user') ?>">Martel</a>
  175. ]]></programlisting>
  176. <para>
  177. Was zu folgender href führt: <filename>user/martel</filename>.
  178. </para>
  179. </note>
  180. <para>
  181. Routen ist ein einfacher Prozess des Durchlaufens aller vorhandenen Routen und
  182. Vergleichens deren Definitionen mit der aktuellen Anfrage URI. Wenn ein positiver
  183. Vergleich gefunden wird, werden variable Werte von der Instanz des Routers
  184. zurückgegeben, und werden für die spätere Verwendung im Dispatcher in das
  185. <classname>Zend_Controller_Request</classname> Objekt iniziiert, sowie in von Benutzern
  186. erstellten Controllern. Bei einem negativen Ergebnis des Vergleiches, wird die nächste
  187. Route in der Kette geprüft.
  188. </para>
  189. <para>
  190. Wenn man herausfinden will welche Route gepasst hat, kann man die
  191. <methodname>getCurrentRouteName()</methodname> Methode verwenden, die den Identifikator
  192. zurückgibt der verwendet wurde als die Route im Router registriert wurde. Wenn man das
  193. aktuelle Route Objekt benötigt, kann <methodname>getCurrentRoute()</methodname>
  194. verwendet werden.
  195. </para>
  196. <note>
  197. <title>Umgekehrter Vergleich</title>
  198. <para>
  199. Routen werden in umgekehrter Reihenfolge verglichen. Deswegen muß sichergestellt
  200. werden das die generellen Routen zuerst definiert werden.
  201. </para>
  202. </note>
  203. <note>
  204. <title>Zurückgegebene Werte</title>
  205. <para>
  206. Werte die vom Routen zurückgegeben werden kommen von URL Parametern oder
  207. Benutzerdefinierten Router Standards. Diese Variablen sind später durch die
  208. <methodname>Zend_Controller_Request::getParam()</methodname> oder
  209. <methodname>Zend_Controller_Action::_getParam()</methodname>Methoden verwendbar.
  210. </para>
  211. </note>
  212. <para>
  213. Es gibt drei spezielle Variablen welche in den Routen verwendet werden können -
  214. 'module', 'controller' und 'action'. Diese speziellen Variablen werden durch
  215. <classname>Zend_Controller_Dispatcher</classname> verwendet um einen Controller und die
  216. Aktion zu funden zu der verwiesen wird.
  217. </para>
  218. <note>
  219. <title>Spezielle Variablen</title>
  220. <para>
  221. Die Namen dieser speziellen Variablen kann unterschiedlich sein wenn entschieden
  222. wird die Standards in <classname>Zend_Controller_Request_Http</classname> mithilfe
  223. der <code>setControllerKey</code> und <code>setActionKey</code> Methode zu Ändern.
  224. </para>
  225. </note>
  226. </sect2>
  227. <sect2 id="zend.controller.router.default-routes">
  228. <title>Standard Routen</title>
  229. <para>
  230. <classname>Zend_Controller_Router_Rewrite</classname> kommt mit einer Standard Route
  231. vorkonfiguriert, welche URIs im Sinn von <filename>controller/action</filename>
  232. entspricht. Zusätzlich kann ein Modul Name als erstes Pfad Element definiert werden,
  233. welches URIs in der Form von <filename>module/controller/action</filename> erlaubt.
  234. Letztendlich wird es auch allen zusätzlichen Parametern entsprechen die der URI
  235. standardmäßig hinzugefügt wurden -
  236. <filename>controller/action/var1/value1/var2/value2</filename>.
  237. </para>
  238. <para>
  239. Einige Beispiele wie solche Routen verglichen werden:
  240. </para>
  241. <programlisting language="php"><![CDATA[
  242. // Folgende Annahme:
  243. $ctrl->setControllerDirectory(
  244. array(
  245. 'default' => '/path/to/default/controllers',
  246. 'news' => '/path/to/news/controllers',
  247. 'blog' => '/path/to/blog/controllers'
  248. )
  249. );
  250. Nur Modul:
  251. http://example/news
  252. module == news
  253. Ungültiges Modul, geht an den Controller Namen:
  254. http://example/foo
  255. controller == foo
  256. Modul + Controller:
  257. http://example/blog/archive
  258. module == blog
  259. controller == archive
  260. Modul + Controller + Aktion:
  261. http://example/blog/archive/list
  262. module == blog
  263. controller == archive
  264. action == list
  265. Modul + Controller + Aktion + Parameter:
  266. http://example/blog/archive/list/sort/alpha/date/desc
  267. module == blog
  268. controller == archive
  269. action == list
  270. sort == alpha
  271. date == desc
  272. ]]></programlisting>
  273. <para>
  274. Die Standardroute ist einfach ein
  275. <classname>Zend_Controller_Router_Route_Module</classname> Objekt welches unter dem
  276. Namen (Index) 'default' im RewriteRouter gespeichert ist. Es wird mehr oder weniger wie
  277. folgt erstellt:
  278. </para>
  279. <programlisting language="php"><![CDATA[
  280. $compat = new Zend_Controller_Router_Route_Module(array(),
  281. $dispatcher,
  282. $request);
  283. $this->addRoute('default', $compat);
  284. ]]></programlisting>
  285. <para>
  286. Wenn diese spezielle Standard Route im eigenen Routing Schema nicht gewünscht ist, kann
  287. Sie durch Erstellung einer eigenen 'default' Route überschrieben werden (z.B. durch
  288. Speichern unter dem Namen 'default') oder dem kompletten Entfernen durch verwenden von
  289. <methodname>removeDefaultRoutes()</methodname>:
  290. </para>
  291. <programlisting language="php"><![CDATA[
  292. // Löschen aller Standard Routen
  293. $router->removeDefaultRoutes();
  294. ]]></programlisting>
  295. </sect2>
  296. <sect2 id="zend.controller.router.rewritebase">
  297. <title>Basis URL und Unterverzeichnisse</title>
  298. <para>
  299. Der Rewrite Router kann in Unterverzeichnissen verwendet werden (z.B.
  300. <filename>http://domain.com/~user/application-root/</filename>) und in diesem Fall
  301. sollte die Basis URL der Anwendung (<filename>/~user/application-root</filename>)
  302. automatisch durch <classname>Zend_Controller_Request_Http</classname> erkannt und auch
  303. verwendet werden.
  304. </para>
  305. <para>
  306. Sollte die Basis URL nicht richtig erkannt werden kann diese mit eigenen Basispfad
  307. überschrieben werden durch Verwendung von
  308. <classname>Zend_Controller_Request_Http</classname> und Auruf der
  309. <methodname>setBaseUrl()</methodname> Methode (siehe
  310. <xref linkend="zend.controller.request.http.baseurl" />):
  311. </para>
  312. <programlisting language="php"><![CDATA[
  313. $request->setBaseUrl('/~user/application-root/');
  314. ]]></programlisting>
  315. </sect2>
  316. <sect2 id="zend.controller.router.global.parameters">
  317. <title>Globale Parameter</title>
  318. <para>
  319. Man kann in einem Router globale Parameter setzen die der Route automatisch zur
  320. Verfügung stehen wenn Sie durch <code>setGlobalParam</code> eingefügt werden. Wenn ein
  321. globaler Parameter gesetzt ist, aber auch direkt an die Assemble Methode gegeben wird,
  322. überschreibt der Benutzer-Parameter den Globalen-Parameter. Globale Parameter können auf
  323. folgendem Weg gesetzt werden:
  324. </para>
  325. <programlisting language="php"><![CDATA[
  326. $router->setGlobalParam('lang', 'en');
  327. ]]></programlisting>
  328. </sect2>
  329. <sect2 id="zend.controller.router.routes">
  330. <title>Router Typen</title>
  331. <xi:include href="Zend_Controller-Router-Route.xml" />
  332. <xi:include href="Zend_Controller-Router-Route-Static.xml" />
  333. <xi:include href="Zend_Controller-Router-Route-Regex.xml" />
  334. <xi:include href="Zend_Controller-Router-Route-Hostname.xml" />
  335. <xi:include href="Zend_Controller-Router-Route-Chain.xml" />
  336. <xi:include href="Zend_Controller-Router-Route-Rest.xml" />
  337. </sect2>
  338. <sect2 id="zend.controller.router.add-config">
  339. <title>Zend_Config mit dem RewriteRouter verwenden</title>
  340. <para>
  341. Manchmal ist es praktischer, eine Konfigurationsdatei mit neuen Routen zu
  342. aktualisieren, als den Code zu ändern. Dies ist mit Hilfe der
  343. <methodname>addConfig()</methodname> Methode möglich. Im Wesentlichen kann man eine
  344. <classname>Zend_Config</classname> kompatible Konfiguration erstellen, in seinem Code
  345. einlesen und an den RewriteRouter übergeben:
  346. </para>
  347. <para>
  348. Als Beispiel wird die folgende INI Datei angenommen:
  349. </para>
  350. <programlisting language="php"><![CDATA[
  351. [production]
  352. routes.archive.route = "archive/:year/*"
  353. routes.archive.defaults.controller = archive
  354. routes.archive.defaults.action = show
  355. routes.archive.defaults.year = 2000
  356. routes.archive.reqs.year = "\d+"
  357. routes.news.type = "Zend_Controller_Router_Route_Static"
  358. routes.news.route = "news"
  359. routes.news.defaults.controller = "news"
  360. routes.news.defaults.action = "list"
  361. routes.archive.type = "Zend_Controller_Router_Route_Regex"
  362. routes.archive.route = "archive/(\d+)"
  363. routes.archive.defaults.controller = "archive"
  364. routes.archive.defaults.action = "show"
  365. routes.archive.map.1 = "year"
  366. ; OR: routes.archive.map.year = 1
  367. ]]></programlisting>
  368. <para>
  369. Die oben angeführte INI Datei kann dann wie folgt in ein
  370. <classname>Zend_Config</classname> Objekt eingelesen werden:
  371. </para>
  372. <programlisting language="php"><![CDATA[
  373. $config = new Zend_Config_Ini('/path/to/config.ini', 'production');
  374. $router = new Zend_Controller_Router_Rewrite();
  375. $router->addConfig($config, 'routes');
  376. ]]></programlisting>
  377. <para>
  378. Im oberen Beispiel teilen wir dem Router mit, den 'routes' Bereich der INI Datei
  379. für seine Routen zu verwenden. Jeder Schlüssel auf erster Ebene in diesem Bereich
  380. wird verwendet, um den Namen der Routen zu definieren; das obige Beispiel definiert
  381. die Routen 'archive' und 'news'. Jede Route erfordert dann mindestens einen 'route'
  382. Eintrag und einen oder mehrere 'defaults' Einträge; optional können eine oder
  383. mehrere 'reqs' (kurz für 'required', d.h. erforderlich) Einträge angegeben werden.
  384. Alles in allem entspricht dies den drei Argumenten, die an ein
  385. <classname>Zend_Controller_Router_Route_Interface</classname> Objekt übergeben werden.
  386. Ein Optionsschlüssel 'type' kann verwendet werden, um den Typ der Routenklasse für
  387. diese Route anzugeben; standardmäßig wird
  388. <classname>Zend_Controller_Router_Route</classname> verwendet. Im obigen Beispiel wird
  389. die 'news' Route definiert, um
  390. <classname>Zend_Controller_Router_Route_Static</classname> zu verwenden.
  391. </para>
  392. </sect2>
  393. <sect2 id="zend.controller.router.subclassing">
  394. <title>Erben vom Router</title>
  395. <para>
  396. Der Standard Rewrite Router sollte die meisten Funktionalitäten die benötigt werden zur
  397. Verfügung stellen; meistens wird es nur notwendig sein einen neuen Router Typen zu
  398. erstellen um neue oder modifizierte Funktionalitäten für die verfügbaren Routen zu
  399. bieten.
  400. </para>
  401. <para>
  402. So gesehen, wird man in einigen Fällen ein anderes Routing Paradigma verwenden wollen.
  403. Das Interface <classname>Zend_Controller_Router_Interface</classname> bietet die
  404. minimalen Information die benötigt werden um einen Router er erstellen und besteht aus
  405. einer einzigen Methode.
  406. </para>
  407. <programlisting language="php"><![CDATA[
  408. interface Zend_Controller_Router_Interface
  409. {
  410. /**
  411. * @param Zend_Controller_Request_Abstract $request
  412. * @throws Zend_Controller_Router_Exception
  413. * @return Zend_Controller_Request_Abstract
  414. */
  415. public function route(Zend_Controller_Request_Abstract $request);
  416. }
  417. ]]></programlisting>
  418. <para>
  419. Das Routing findet nur einmal statt, wenn die Anfrage das erste Mal vom System erhalten
  420. wird. Der Zweck des Routers ist es, Controller, Aktion und optionale Parameter auf Basis
  421. der Anfrageumgebung zu ermitteln und im Request zu setzen. Das Request Objekt wird dann
  422. an den Dispatcher übergeben. Wenn es nicht möglich ist, eine Route auf einen Dispatch
  423. Token abzubilden, soll der Router nichts mit dem Request Objekt machen.
  424. </para>
  425. </sect2>
  426. </sect1>
  427. <!--
  428. vim:se ts=4 sw=4 et:
  429. -->