Zend_Controller-Router.xml 21 KB

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