Zend_Controller-Router.xml 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  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>Routeur Standard</title>
  6. <sect2 id="zend.controller.router.introduction">
  7. <title>Introduction</title>
  8. <para>
  9. <classname>Zend_Controller_Router_Rewrite</classname> est le routeur par défaut
  10. du framework. Le routage consiste à analyser l'URI définie (la partie après l'URL de
  11. base) et la décomposer en valeurs déterminant quels module, contrôleur et action
  12. doivent recevoir la requête. Ces valeurs sont encapsulées dans un objet de requête
  13. <classname>Zend_Controller_Request_Http</classname> qui est alors injecté dans
  14. <classname>Zend_Controller_Dispatcher_Standard</classname> pour y être traité Le
  15. routage n'est effectué qu'une seule fois par requête&#160;: juste avant que le premier
  16. contrôleur ne soit traité (distribué)
  17. </para>
  18. <para>
  19. <classname>Zend_Controller_Router_Rewrite</classname> intervient pour fournir un
  20. environnement de requête similaire à "mod_rewrite", tout en utilisant uniquement du
  21. <acronym>PHP</acronym>. Il est désigné sur les principes de Ruby on Rails et ne requière pas de
  22. connaissances particulières en réécriture d'URL. Il est destiné à fonctionner avec une
  23. seule règle de réécriture Apache, dont voici des exemples&#160;:
  24. </para>
  25. <programlisting language="php"><![CDATA[
  26. RewriteEngine on
  27. RewriteRule !\.(js|ico|gif|jpg|png|css|html)$ index.php
  28. ]]></programlisting>
  29. <para>ou (recommandé) :</para>
  30. <programlisting language="php"><![CDATA[
  31. RewriteEngine On
  32. RewriteCond %{REQUEST_FILENAME} -s [OR]
  33. RewriteCond %{REQUEST_FILENAME} -l [OR]
  34. RewriteCond %{REQUEST_FILENAME} -d
  35. RewriteRule ^.*$ - [NC,L]
  36. RewriteRule ^.*$ index.php [NC,L]
  37. ]]></programlisting>
  38. <para>
  39. Le routeur de réécriture peut aussi être utilisé avec un serveur Web <acronym>IIS</acronym>
  40. (versions &lt;= 7.0) si <ulink url="http://www.isapirewrite.com">Isapi_Rewrite</ulink>
  41. a été installée comme une extension Isap avec la règle suivante&#160;:
  42. </para>
  43. <programlisting language="php"><![CDATA[
  44. RewriteRule ^[\w/\%]*(?:\.(?!(?:js|ico|gif|jpg|png|css|html)$)[\w\%]*$)? /index.php [I]
  45. ]]></programlisting>
  46. <note>
  47. <title>IIS Isapi_Rewrite</title>
  48. <para>
  49. Lorsque <acronym>IIS</acronym> est utilisé, <varname>$_SERVER['REQUEST_URI']</varname> n'existera pas
  50. ou vaudra une chaîne vide. Dans ce cas,
  51. <classname>Zend_Controller_Request_Http</classname> essaiera d'utiliser la valeur
  52. de <varname>$_SERVER['HTTP_X_REWRITE_URL']</varname>, initialisée par l'extension
  53. Isapi_Rewrite.
  54. </para>
  55. </note>
  56. <para>
  57. <acronym>IIS</acronym> 7.0 introduit un moodule de réécriture d'URL natif, et il peut être configuré
  58. comme ceci&#160;:
  59. </para>
  60. <programlisting language="xml"><![CDATA[
  61. <?xml version="1.0" encoding="UTF-8"?>
  62. <configuration>
  63. <system.webServer>
  64. <rewrite>
  65. <rules>
  66. <rule name="Imported Rule 1" stopProcessing="true">
  67. <match url="^.*$" />
  68. <conditions logicalGrouping="MatchAny">
  69. <add input="{REQUEST_FILENAME}"
  70. matchType="IsFile" pattern=""
  71. ignoreCase="false" />
  72. <add input="{REQUEST_FILENAME}"
  73. matchType="IsDirectory"
  74. pattern="" ignoreCase="false" />
  75. </conditions>
  76. <action type="None" />
  77. </rule>
  78. <rule name="Imported Rule 2" stopProcessing="true">
  79. <match url="^.*$" />
  80. <action type="Rewrite" url="index.php" />
  81. </rule>
  82. </rules>
  83. </rewrite>
  84. </system.webServer>
  85. </configuration>
  86. ]]></programlisting>
  87. <para>Si vous utilisez Lighttpd, la règle de réécriture suivante est valide&#160;:</para>
  88. <programlisting language="lighttpd"><![CDATA[
  89. url.rewrite-once = (
  90. ".*\?(.*)$" => "/index.php?$1",
  91. ".*\.(js|ico|gif|jpg|png|css|html)$" => "$0",
  92. "" => "/index.php"
  93. )
  94. ]]></programlisting>
  95. </sect2>
  96. <sect2 id="zend.controller.router.usage">
  97. <title>Utilisation d'un routeur</title>
  98. <para>
  99. Pour utiliser un routeur et le configurer, vous devez le récupérer et ajouter des
  100. routes&#160;:
  101. </para>
  102. <programlisting language="php"><![CDATA[
  103. /* Créer un routeur */
  104. $router = $frontctrl->getRouter();
  105. // retourne un routeur de réécriture par défaut
  106. $router->addRoute(
  107. 'user',
  108. new Zend_Controller_Router_Route('user/:username',
  109. array('controller' => 'user',
  110. 'action' => 'info'))
  111. );
  112. ]]></programlisting>
  113. </sect2>
  114. <sect2 id="zend.controller.router.basic">
  115. <title>Utilisation basique du routeur de réécriture</title>
  116. <para>
  117. Le coeur de ce routeur repose sur le concept de routes personnalisées. Les routes
  118. sont ajoutées en appelant la méthode <methodname>addRoute()</methodname> et en lui passant une
  119. instance implémentant <classname>Zend_Controller_Router_Route_Interface</classname>.
  120. Exemple&#160;:
  121. </para>
  122. <programlisting language="php"><![CDATA[
  123. $router->addRoute('user',
  124. new Zend_Controller_Router_Route('user/:username'));
  125. ]]></programlisting>
  126. <para>
  127. Le routeur de réécriture est fourni avec six types de route, dont une
  128. spéciale&#160;:
  129. </para>
  130. <itemizedlist mark="opencircle">
  131. <listitem>
  132. <para>
  133. <link
  134. linkend="zend.controller.router.routes.standard">Zend_Controller_Router_Route</link>
  135. </para>
  136. </listitem>
  137. <listitem>
  138. <para>
  139. <link
  140. linkend="zend.controller.router.routes.static">Zend_Controller_Router_Route_Static</link>
  141. </para>
  142. </listitem>
  143. <listitem>
  144. <para>
  145. <link
  146. linkend="zend.controller.router.routes.regex">Zend_Controller_Router_Route_Regex</link>
  147. </para>
  148. </listitem>
  149. <listitem>
  150. <para>
  151. <link
  152. linkend="zend.controller.router.routes.hostname">Zend_Controller_Router_Route_Hostname</link>
  153. </para>
  154. </listitem>
  155. <listitem>
  156. <para>
  157. <link
  158. linkend="zend.controller.router.routes.chain">Zend_Controller_Router_Route_Chain</link>
  159. </para>
  160. </listitem>
  161. <listitem>
  162. <para>
  163. <link
  164. linkend="zend.controller.router.default-routes">Zend_Controller_Router_Rewrite</link>&#160;*
  165. </para>
  166. </listitem>
  167. </itemizedlist>
  168. <para>
  169. Chaque route peut être utilisée plusieurs fois pour créer un chaîne de routes
  170. représentant un schéma de routage personnalisé. La route du module, en revanche, ne
  171. devrait être utilisée qu'une seule fois, elle est en générale la route la plus
  172. générique (par défaut). Chaque route sera définie un peu plus tard.
  173. </para>
  174. <para>
  175. Le premier paramètre de <code>addRoute</code> est le nom de la route. Il sera
  176. utilisé plus tard pour la sélectionner (par exemple pour générer un <acronym>URL</acronym>. Le deuxième
  177. paramètre étant l'objet route lui-même.
  178. </para>
  179. <note>
  180. <para>
  181. L'utilisation la plus plausible du nom de la route est illustrée dans l'aide
  182. vue "url"&#160;:
  183. </para>
  184. <programlisting language="php"><![CDATA[
  185. <a href="<?php echo $this->url(array('username' => 'martel'), 'user') ?>">
  186. Martel
  187. </a>
  188. ]]></programlisting>
  189. <para>Ce qui donnera un "href"&#160;: <code>user/martel</code>.</para>
  190. </note>
  191. <para>
  192. Le routage consiste simplement à itérer toutes les routes reçues et à les faire
  193. correspondre à l'URI de la requête courante. Dès qu'une correspondance est établie, les
  194. variables sont injectées dans l'objet <classname>Zend_Controller_Request</classname>
  195. utilisé après dans le distributeur et dans les contrôleurs. Si aucune correspondance
  196. n'est trouvée, la route suivante dans la pile est analysée.
  197. </para>
  198. <para>
  199. Si vous devez déterminer quelle route a été trouvée, vous pouvez utilisez la
  200. méthode <methodname>getCurrentRouteName()</methodname>, qui vous retournera l'identifiant utilisé
  201. pour enregistrer la route dans le routeur. Si vous souhaitez récupérer l'objet de la
  202. route actuelle, vous pouvez utiliser <methodname>getCurrentRoute()</methodname>.
  203. </para>
  204. <note>
  205. <title>Pile LIFO</title>
  206. <para>
  207. Les routes sont analysées dans l'ordre LIFO : dernière fournie, première
  208. analysée. Veillez à définir les routes les génériques en premier donc.
  209. </para>
  210. </note>
  211. <note>
  212. <title>Paramètres de la requête</title>
  213. <para>
  214. Les paramètres de la requête proviennent de l'utilisateur, ou des routes
  215. définies. Ils seront plus tard accessibles via
  216. <methodname>Zend_Controller_Request::getParam()</methodname> ou la méthode
  217. <methodname>Zend_Controller_Action::_getParam()</methodname>.
  218. </para>
  219. </note>
  220. <para>
  221. Il y a trois valeurs spéciales qui peuvent être utilisées dans la définition de
  222. vos routes&#160;: - "module", "controller" et "action" -. Ces valeurs sont utilisées par
  223. <classname>Zend_Controller_Dispatcher</classname> pour trouver les contrôleurs et
  224. action à distribuer.
  225. </para>
  226. <note>
  227. <title>Valeurs spéciales</title>
  228. <para>
  229. Le nom de ces valeurs peut être changé dans
  230. <classname>Zend_Controller_Request_Http</classname> avec les méthodes
  231. <code>setControllerKey</code> et <code>setActionKey</code>.
  232. </para>
  233. </note>
  234. </sect2>
  235. <sect2 id="zend.controller.router.default-routes">
  236. <title>Routes par défaut</title>
  237. <para>
  238. Zend_Controller_Router_Rewrite possède des routes par défaut qui vont
  239. correspondre pour des <acronym>URI</acronym> du type <code>controller/action</code>. De plus, un nom de
  240. module peut être spécifié comme premier élément du chemin, autorisant ainsi des <acronym>URI</acronym> du
  241. type <code>module/controller/action</code>. Enfin, chaque paramètres de la requête sera
  242. trouvé à la fin de la requête, comme
  243. <code>controller/action/var1/value1/var2/value2</code>.
  244. </para>
  245. <para>Exemples avec ces routes&#160;:</para>
  246. <programlisting language="php"><![CDATA[
  247. // Considérons :
  248. $ctrl->setControllerDirectory(
  249. array(
  250. 'default' => '/path/to/default/controllers',
  251. 'news' => '/path/to/news/controllers',
  252. 'blog' => '/path/to/blog/controllers'
  253. )
  254. );
  255. Module seulement:
  256. http://example/news
  257. module == news
  258. Un module invalide dirige vers le contrôleur:
  259. http://example/foo
  260. controller == foo
  261. Module + controller:
  262. http://example/blog/archive
  263. module == blog
  264. controller == archive
  265. Module + controller + action:
  266. http://example/blog/archive/list
  267. module == blog
  268. controller == archive
  269. action == list
  270. Module + controller + action + params:
  271. http://example/blog/archive/list/sort/alpha/date/desc
  272. module == blog
  273. controller == archive
  274. action == list
  275. sort == alpha
  276. date == desc
  277. ]]></programlisting>
  278. <para>
  279. La route par défaut est simplement un objet
  280. <classname>Zend_Controller_Router_Route_Module</classname>, stocké sous le nom
  281. "default" dans le routeur de réécriture(RewriteRouter). Il est conçu comme ceci&#160;:
  282. </para>
  283. <programlisting language="php"><![CDATA[
  284. $compat = new Zend_Controller_Router_Route_Module(array(),
  285. $dispatcher,
  286. $request);
  287. $this->addRoute('default', $compat);
  288. ]]></programlisting>
  289. <para>
  290. Si vous ne souhaitez pas cette route par défaut, créez en une et stocker la avec
  291. le nom "default" (écrasement), ou supprimez la route avec
  292. <methodname>removeDefaultRoutes()</methodname>&#160;:
  293. </para>
  294. <programlisting language="php"><![CDATA[
  295. // Supprime les routes par défaut
  296. $router->removeDefaultRoutes();
  297. ]]></programlisting>
  298. </sect2>
  299. <sect2 id="zend.controller.router.rewritebase">
  300. <title>Base URL et sous dossiers</title>
  301. <para>
  302. Le routeur de réécriture peut être utilisé dans des sous dossiers (comme
  303. <code>http://domain.com/~user/application-root/</code>), dans un tél cas, l'URL de base
  304. de l'application (<code>/~user/application-root</code>) devrait être automatiquement
  305. détectée par <classname>Zend_Controller_Request_Http</classname> et utilisée
  306. ensuite.
  307. </para>
  308. <para>
  309. Si ça n'était pas le cas, vous pouvez spécifier votre propre base <acronym>URL</acronym>
  310. dans <classname>Zend_Controller_Request_Http</classname> en appelant
  311. <methodname>setBaseUrl()</methodname> (voyez <link
  312. linkend="zend.controller.request.http.baseurl">Base de l'URL et
  313. sous-dossiers</link>)&#160;:
  314. </para>
  315. <programlisting language="php"><![CDATA[
  316. $request->setBaseUrl('/~user/application-root/');
  317. ]]></programlisting>
  318. </sect2>
  319. <sect2 id="zend.controller.router.global.parameters">
  320. <title>Paramètres globaux</title>
  321. <para>
  322. Vous pouvez régler des paramètres globaux dans un routeur, qui sont
  323. automatiquement fournis à la route lors de son assemblage, grâce à la fonction
  324. <methodname>setGlobalParam()</methodname>. Si un paramètre global est réglé mais qu'il est aussi
  325. fourni directement à la méthode d'assemblage, le paramètre utilisateur écrase le
  326. paramètre global. Vous pouvez régler un paramètre global de cette manière&#160;:
  327. </para>
  328. <programlisting language="php"><![CDATA[
  329. $router->setGlobalParam('lang', 'en');
  330. ]]></programlisting>
  331. </sect2>
  332. <sect2 id="zend.controller.router.routes">
  333. <title>Types de route</title>
  334. <xi:include href="Zend_Controller-Router-Route.xml" />
  335. <xi:include href="Zend_Controller-Router-Route-Static.xml" />
  336. <xi:include href="Zend_Controller-Router-Route-Regex.xml" />
  337. <xi:include href="Zend_Controller-Router-Route-Hostname.xml" />
  338. <xi:include href="Zend_Controller-Router-Route-Chain.xml">
  339. <xi:fallback>
  340. <xi:include href="../../en/module_specs/Zend_Controller-Router-Route-Chain.xml" />
  341. </xi:fallback>
  342. </xi:include>
  343. <xi:include href="Zend_Controller-Router-Route-Rest.xml">
  344. <xi:fallback>
  345. <xi:include href="../../en/module_specs/Zend_Controller-Router-Route-Rest.xml" />
  346. </xi:fallback>
  347. </xi:include>
  348. </sect2>
  349. <sect2 id="zend.controller.router.add-config">
  350. <title>Utiliser Zend_Config avec le RewriteRouter</title>
  351. <para>
  352. Il arrive qu'il soit plus commode d'éditer un fichier de configuration de routes,
  353. plutôt que d'éditer un code source. Ceci est rendu possible par la méthode
  354. <methodname>addConfig()</methodname>. Vous créez un objet compatible Zend_Config et vous le passez
  355. à cette méthode.
  356. </para>
  357. <para>Par exemple, voyons un fichier <acronym>INI</acronym> :</para>
  358. <programlisting language="php"><![CDATA[
  359. [production]
  360. routes.archive.route = "archive/:year/*"
  361. routes.archive.defaults.controller = archive
  362. routes.archive.defaults.action = show
  363. routes.archive.defaults.year = 2000
  364. routes.archive.reqs.year = "\d+"
  365. routes.news.type = "Zend_Controller_Router_Route_Static"
  366. routes.news.route = "news"
  367. routes.news.defaults.controller = "news"
  368. routes.news.defaults.action = "list"
  369. routes.archive.type = "Zend_Controller_Router_Route_Regex"
  370. routes.archive.route = "archive/(\d+)"
  371. routes.archive.defaults.controller = "archive"
  372. routes.archive.defaults.action = "show"
  373. routes.archive.map.1 = "year"
  374. ; OU: routes.archive.map.year = 1
  375. ]]></programlisting>
  376. <para>
  377. Ce fichier <acronym>INI</acronym> peut être lu dans grâce à un objet <classname>Zend_Config</classname>
  378. comme suit&#160;:
  379. </para>
  380. <programlisting language="php"><![CDATA[
  381. $config = new Zend_Config_Ini('/path/to/config.ini', 'production');
  382. $router = new Zend_Controller_Router_Rewrite();
  383. $router->addConfig($config, 'routes');
  384. ]]></programlisting>
  385. <para>
  386. Nous indiquons au routeur d'utiliser la section "routes" du fichier <acronym>INI</acronym>. Chaque
  387. clé de premier niveau représente le nom de la route, ainsi nous avons dans l'exemple ci
  388. dessus "archive" et "news". Chaque route attend alors au moins une entrée "route" avec
  389. une ou plusieurs entrées "defaults"&#160;; optionnellement nous pouvons rajouter des
  390. paramètres obligatoires. Tout ceci correspond aux trois arguments fournis par l'objet
  391. implémentant <classname>Zend_Controller_Router_Route_Interface</classname>. Une entrée
  392. optionnelle "type" peut être utilisée pour indiquer le type de classe de routage à
  393. utiliser, il s'agit par défaut de <classname>Zend_Controller_Router_Route</classname>.
  394. Dans l'exemple au dessus, la route "news" va utiliser
  395. <classname>Zend_Controller_Router_Route_Static</classname>.
  396. </para>
  397. </sect2>
  398. <sect2 id="zend.controller.router.subclassing">
  399. <title>Dérivation de l'objet Router</title>
  400. <para>
  401. Le routeur par défaut, dit de réécriture, devrait suffire dans la majorité des
  402. projets. Tout ce qu'il peut être nécessaire de faire, est d'ajouter des routes
  403. particulières selon vos besoins.
  404. </para>
  405. <para>
  406. Cependant, si vous voulez utiliser votre propre logique de routage, une interface
  407. est disponible. <classname>Zend_Controller_Router_Interface</classname> ne définit
  408. qu'une seule méthode&#160;:
  409. </para>
  410. <programlisting language="php"><![CDATA[
  411. interface Zend_Controller_Router_Interface
  412. {
  413. /**
  414. * @param Zend_Controller_Request_Abstract $request
  415. * @throws Zend_Controller_Router_Exception
  416. * @return Zend_Controller_Request_Abstract
  417. */
  418. public function route(Zend_Controller_Request_Abstract $request);
  419. }
  420. ]]></programlisting>
  421. <para>
  422. Le processus de routage n'intervient qu'une fois : lorsque la requête est reçue
  423. par le système. Le routeur doit alors déterminer un contrôleur, une action et de
  424. paramètres optionnel et les spécifier dans un objet de requête, qui est ensuite passé
  425. au distributeur. Si il n'est pas possible de router une requête, alors l'objet de
  426. requête devrait être laissé tel-quel.
  427. </para>
  428. </sect2>
  429. </sect1>