Zend_Controller-Router.xml 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <!-- EN-Revision: 15103 -->
  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. PHP. 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 role="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 role="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 IIS
  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 role="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 IIS est utilisé, <code>$_SERVER['REQUEST_URI']</code> 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 <code>$_SERVER['HTTP_X_REWRITE_URL']</code>, initialisée par l'extension
  53. Isapi_Rewrite.
  54. </para>
  55. </note>
  56. <para>
  57. IIS 7.0 introduit un moodule de réécriture d'URL natif, et il peut être configuré
  58. comme ceci&#160;:
  59. </para>
  60. <programlisting role="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 role="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 role="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 <code>addRoute()</code> et en lui passant une
  119. instance implémentant <classname>Zend_Controller_Router_Route_Interface</classname>.
  120. Exemple&#160;:
  121. </para>
  122. <programlisting role="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 quatre types de route, dont une
  128. spéciale&#160;:
  129. </para>
  130. <itemizedlist mark="opencircle">
  131. <listitem>
  132. <para><xref linkend="zend.controller.router.routes.standard" /></para>
  133. </listitem>
  134. <listitem>
  135. <para><xref linkend="zend.controller.router.routes.static" /></para>
  136. </listitem>
  137. <listitem>
  138. <para><xref linkend="zend.controller.router.routes.regex" /></para>
  139. </listitem>
  140. <listitem>
  141. <para><xref linkend="zend.controller.router.default-routes" /> *</para>
  142. </listitem>
  143. </itemizedlist>
  144. <para>
  145. Chaque route peut être utilisée plusieurs fois pour créer un chaîne de routes
  146. représentant un schéma de routage personnalisé. La route du module, en revanche, ne
  147. devrait être utilisée qu'une seule fois, elle est en générale la route la plus
  148. générique (par défaut). Chaque route sera définie un peu plus tard.
  149. </para>
  150. <para>
  151. Le premier paramètre de <code>addRoute</code> est le nom de la route. Il sera
  152. utilisé plus tard pour la sélectionner (par exemple pour générer un URL. Le deuxième
  153. paramètre étant l'objet route lui-même.
  154. </para>
  155. <note>
  156. <para>
  157. L'utilisation la plus plausible du nom de la route est illustrée dans l'aide
  158. vue "url"&#160;:
  159. </para>
  160. <programlisting role="php"><![CDATA[
  161. <a href="<?= $this->url(array('username' => 'martel'), 'user') ?>">
  162. Martel
  163. </a>
  164. ]]></programlisting>
  165. <para>Ce qui donnera un "href"&#160;: <code>user/martel</code>.</para>
  166. </note>
  167. <para>
  168. Le routage consiste simplement à itérer toutes les routes reçues et à les faire
  169. correspondre à l'URI de la requête courante. Dès qu'une correspondance est établie, les
  170. variables sont injectées dans l'objet <classname>Zend_Controller_Request</classname>
  171. utilisé après dans le distributeur et dans les contrôleurs. Si aucune correspondance
  172. n'est trouvée, la route suivante dans la pile est analysée.
  173. </para>
  174. <para>
  175. Si vous devez déterminer quelle route a été trouvée, vous pouvez utilisez la
  176. méthode <code>getCurrentRouteName()</code>, qui vous retournera l'identifiant utilisé
  177. pour enregistrer la route dans le routeur. Si vous souhaitez récupérer l'objet de la
  178. route actuelle, vous pouvez utiliser <code>getCurrentRoute()</code>.
  179. </para>
  180. <note>
  181. <title>Pile LIFO</title>
  182. <para>
  183. Les routes sont analysées dans l'ordre LIFO : dernière fournie, première
  184. analysée. Veillez à définir les routes les génériques en premier donc.
  185. </para>
  186. </note>
  187. <note>
  188. <title>Paramètres de la requête</title>
  189. <para>
  190. Les paramètres de la requête proviennent de l'utilisateur, ou des routes
  191. définies. Ils seront plus tard accessibles via
  192. <classname>Zend_Controller_Request::getParam()</classname> ou la méthode
  193. <classname>Zend_Controller_Action::_getParam()</classname>.
  194. </para>
  195. </note>
  196. <para>
  197. Il y a trois valeurs spéciales qui peuvent être utilisées dans la définition de
  198. vos routes&#160;: - "module", "controller" et "action" -. Ces valeurs sont utilisées par
  199. <classname>Zend_Controller_Dispatcher</classname> pour trouver les contrôleurs et
  200. action à distribuer.
  201. </para>
  202. <note>
  203. <title>Valeurs spéciales</title>
  204. <para>
  205. Le nom de ces valeurs peut être changé dans
  206. <classname>Zend_Controller_Request_Http</classname> avec les méthodes
  207. <code>setControllerKey</code> et <code>setActionKey</code>.
  208. </para>
  209. </note>
  210. </sect2>
  211. <sect2 id="zend.controller.router.default-routes">
  212. <title>Routes par défaut</title>
  213. <para>
  214. Zend_Controller_Router_Rewrite possède des routes par défaut qui vont
  215. correspondre pour des URI du type <code>controller/action</code>. De plus, un nom de
  216. module peut être spécifié comme premier élément du chemin, autorisant ainsi des URI du
  217. type <code>module/controller/action</code>. Enfin, chaque paramètres de la requête sera
  218. trouvé à la fin de la requête, comme
  219. <code>controller/action/var1/value1/var2/value2</code>.
  220. </para>
  221. <para>Exemples avec ces routes&#160;:</para>
  222. <programlisting role="php"><![CDATA[
  223. // Considérons :
  224. $ctrl->setControllerDirectory(
  225. array(
  226. 'default' => '/path/to/default/controllers',
  227. 'news' => '/path/to/news/controllers',
  228. 'blog' => '/path/to/blog/controllers'
  229. )
  230. );
  231. Module seulement:
  232. http://example/news
  233. module == news
  234. Un module invalide dirige vers le contrôleur:
  235. http://example/foo
  236. controller == foo
  237. Module + controller:
  238. http://example/blog/archive
  239. module == blog
  240. controller == archive
  241. Module + controller + action:
  242. http://example/blog/archive/list
  243. module == blog
  244. controller == archive
  245. action == list
  246. Module + controller + action + params:
  247. http://example/blog/archive/list/sort/alpha/date/desc
  248. module == blog
  249. controller == archive
  250. action == list
  251. sort == alpha
  252. date == desc
  253. ]]></programlisting>
  254. <para>
  255. La route par défaut est simplement un objet
  256. <classname>Zend_Controller_Router_Route_Module</classname>, stocké sous le nom
  257. "default" dans le routeur de réécriture(RewriteRouter). Il est conçu comme ceci&#160;:
  258. </para>
  259. <programlisting role="php"><![CDATA[
  260. $compat = new Zend_Controller_Router_Route_Module(array(),
  261. $dispatcher,
  262. $request);
  263. $this->addRoute('default', $compat);
  264. ]]></programlisting>
  265. <para>
  266. Si vous ne souhaitez pas cette route par défaut, créez en une et stocker la avec
  267. le nom "default" (écrasement), ou supprimez la route avec
  268. <code>removeDefaultRoutes()</code>&#160;:
  269. </para>
  270. <programlisting role="php"><![CDATA[
  271. // Supprime les routes par défaut
  272. $router->removeDefaultRoutes();
  273. ]]></programlisting>
  274. </sect2>
  275. <sect2 id="zend.controller.router.rewritebase">
  276. <title>Base URL et sous dossiers</title>
  277. <para>
  278. Le routeur de réécriture peut être utilisé dans des sous dossiers (comme
  279. <code>http://domain.com/~user/application-root/</code>), dans un tél cas, l'URL de base
  280. de l'application (<code>/~user/application-root</code>) devrait être automatiquement
  281. détectée par <classname>Zend_Controller_Request_Http</classname> et utilisée
  282. ensuite.
  283. </para>
  284. <para>
  285. Si ça n'était pas le cas, vous pouvez spécifier votre propre base URL dans
  286. <classname>Zend_Controller_Request_Http</classname> en appelant
  287. <code>setBaseUrl()</code> (voyez
  288. <xref linkend="zend.controller.request.http.baseurl" />)&#160;:
  289. </para>
  290. <programlisting role="php"><![CDATA[
  291. $request->setBaseUrl('/~user/application-root/');
  292. ]]></programlisting>
  293. </sect2>
  294. <sect2 id="zend.controller.router.global.parameters">
  295. <title>Paramètres globaux</title>
  296. <para>
  297. Vous pouvez régler des paramètres globaux dans un routeur, qui sont
  298. automatiquement fournis à la route lors de son assemblage, grâce à la fonction
  299. <code>setGlobalParam()</code>. Si un paramètre global est réglé mais qu'il est aussi
  300. fourni directement à la méthode d'assemblage, le paramètre utilisateur écrase le
  301. paramètre global. Vous pouvez régler un paramètre global de cette manière&#160;:
  302. </para>
  303. <programlisting role="php"><![CDATA[
  304. $router->setGlobalParam('lang', 'en');
  305. ]]></programlisting>
  306. </sect2>
  307. <sect2 id="zend.controller.router.routes">
  308. <title>Types de route</title>
  309. <xi:include href="Zend_Controller-Router-Route.xml" />
  310. <xi:include href="Zend_Controller-Router-Route-Static.xml" />
  311. <xi:include href="Zend_Controller-Router-Route-Regex.xml" />
  312. <xi:include href="Zend_Controller-Router-Route-Hostname.xml" />
  313. </sect2>
  314. <sect2 id="zend.controller.router.add-config">
  315. <title>Utiliser Zend_Config avec le RewriteRouter</title>
  316. <para>
  317. Il arrive qu'il soit plus commode d'éditer un fichier de configuration de routes,
  318. plutôt que d'éditer un code source. Ceci est rendu possible par la méthode
  319. <code>addConfig()</code>. Vous créez un objet compatible Zend_Config et vous le passez
  320. à cette méthode.
  321. </para>
  322. <para>Par exemple, voyons un fichier INI :</para>
  323. <programlisting role="php"><![CDATA[
  324. [production]
  325. routes.archive.route = "archive/:year/*"
  326. routes.archive.defaults.controller = archive
  327. routes.archive.defaults.action = show
  328. routes.archive.defaults.year = 2000
  329. routes.archive.reqs.year = "\d+"
  330. routes.news.type = "Zend_Controller_Router_Route_Static"
  331. routes.news.route = "news"
  332. routes.news.defaults.controller = "news"
  333. routes.news.defaults.action = "list"
  334. routes.archive.type = "Zend_Controller_Router_Route_Regex"
  335. routes.archive.route = "archive/(\d+)"
  336. routes.archive.defaults.controller = "archive"
  337. routes.archive.defaults.action = "show"
  338. routes.archive.map.1 = "year"
  339. ; OU: routes.archive.map.year = 1
  340. ]]></programlisting>
  341. <para>
  342. Ce fichier INI peut être lu dans grâce à un objet <classname>Zend_Config</classname>
  343. comme suit&#160;:
  344. </para>
  345. <programlisting role="php"><![CDATA[
  346. $config = new Zend_Config_Ini('/path/to/config.ini', 'production');
  347. $router = new Zend_Controller_Router_Rewrite();
  348. $router->addConfig($config, 'routes');
  349. ]]></programlisting>
  350. <para>
  351. Nous indiquons au routeur d'utiliser la section "routes" du fichier INI. Chaque
  352. clé de premier niveau représente le nom de la route, ainsi nous avons dans l'exemple ci
  353. dessus "archive" et "news". Chaque route attend alors au moins une entrée "route" avec
  354. une ou plusieurs entrées "defaults"&#160;; optionnellement nous pouvons rajouter des
  355. paramètres obligatoires. Tout ceci correspond aux trois arguments fournis par l'objet
  356. implémentant <classname>Zend_Controller_Router_Route_Interface</classname>. Une entrée
  357. optionnelle "type" peut être utilisée pour indiquer le type de classe de routage à
  358. utiliser, il s'agit par défaut de <classname>Zend_Controller_Router_Route</classname>.
  359. Dans l'exemple au dessus, la route "news" va utiliser
  360. <classname>Zend_Controller_Router_Route_Static</classname>.
  361. </para>
  362. </sect2>
  363. <sect2 id="zend.controller.router.subclassing">
  364. <title>Dérivation de l'objet Router</title>
  365. <para>
  366. Le routeur par défaut, dit de réécriture, devrait suffire dans la majorité des
  367. projets. Tout ce qu'il peut être nécessaire de faire, est d'ajouter des routes
  368. particulières selon vos besoins.
  369. </para>
  370. <para>
  371. Cependant, si vous voulez utiliser votre propre logique de routage, une interface
  372. est disponible. <classname>Zend_Controller_Router_Interface</classname> ne définit
  373. qu'une seule méthode&#160;:
  374. </para>
  375. <programlisting role="php"><![CDATA[
  376. interface Zend_Controller_Router_Interface
  377. {
  378. /**
  379. * @param Zend_Controller_Request_Abstract $request
  380. * @throws Zend_Controller_Router_Exception
  381. * @return Zend_Controller_Request_Abstract
  382. */
  383. public function route(Zend_Controller_Request_Abstract $request);
  384. }
  385. ]]></programlisting>
  386. <para>
  387. Le processus de routage n'intervient qu'une fois : lorsque la requête est reçue
  388. par le système. Le routeur doit alors déterminer un contrôleur, une action et de
  389. paramètres optionnel et les spécifier dans un objet de requête, qui est ensuite passé
  390. au distributeur. Si il n'est pas possible de router une requête, alors l'objet de
  391. requête devrait être laissé tel-quel.
  392. </para>
  393. </sect2>
  394. </sect1>