Voici un petit tutoriel très simple pour créer une route personnalisée à votre application Zend Framework.
Donc avons toujours notre cher bootstrap dans lequel nous allons ajouter la méthode Bootstrap::_initRouter() pour ajouter notre route.
1 2 3 4 5 6 7 8 | <?php class Bootstrap extends Zend_Application_Bootstrap_Bootstrap { protected function _initRouter() { // Ici notre code } } |
Qu’allons nous faire ?
Si nous voulons par exemple faire ce qu’il y a de plus classique : de la réécriture d’URL avec le Zend Framework, vous ne pouvez évidemment pas passer par la configuration Apache car le routeur par défaut du Zend Framework analyse l’URI et la segmente en 3 parties (module/controller/action) et si l’URI est plus longue, les autres segments seront considérés comme paramètres.
En savoir plus dans la section dédiée.
Ici, nous faire quelque chose de simple, un controller et une son action par défaut (indexAction()) pour gérer des URI suivant un certain pattern qui sera, par exemple :
http://domain/article/2009-26-mon-article-de-ouf.html
http://domain/article/2009-2-mon-2nd-article.htm
// etc.
Pour cela, nous allons récupérer notre router par défaut via cette ligne :
<?php $router = Zend_Controller_Front::getInstance()->getRouter();
Ensuite nous allons créer notre nouvelle route personnalisée qui sera l’objet d’une instance de classe Zend_Controller_Router_Route_Regex.
Le constructeur de cette classe déclare 4 paramètres dont un obligatoire :
- Le pattern de la route (donc son expression régulière) ;
- Un tableau spécifiant à quel controller/action vous allez associer la route ;
- Un tableau permettant de mapper les numéros de paramètre ;
- Le pattern permettant de générer vos URI avec l’aide de vue url().
Construisons notre nouvelle route en essayant de comprendre l’intérêt de chacun des paramètres :
1 2 3 4 5 6 7 8 9 | <?php $route = new Zend_Controller_Router_Route_Regex('article/(\d+)-(\d+)-([-\w]+)\.html?', array( 'controller' => 'article', 'action' => 'index' ), array( 1 => 'article_year', 2 => 'article_id', 3 => 'article_title_uri' ), 'article/%s-%s-%s.html'); |
Nous avons bel et bien notre expression régulière en premier paramètre qui va mapper nos pages vers la route que nous avons défini dans le tableau du second paramètre. Ensuite viennent les 2 autres paramètres.
Si vous êtes familier des expressions régulières, vous saurez que les paramètres sont identifiés par les sous-expressions qui sont situées dans les parenthèses de l’expression globale (ici ce sera (d), (d) et ([-w])) ; et qu’on récupère via la variable $1 pour la première parenthèse, $2 pour la seconde, etc.
Le troisième paramètre va nous permettre de remplacer ces numéros de paramètres par des noms plus facilement identifiables et utilisables.
Explications : c’est comme si au lieu d’avoir une expression qui ressemblerait à cela : article/$1-$2-$3.html, nous aurions ceci : article/$article_year-$article_id-$article_title_uri.html.
Avouez que c’est déjà bien plus agréable pour traiter les paramètres… Personnellement, je trouve que c’est vraiment une bonne initiative d’avoir permis de mapper les paramètres et vous allez comprendre pourquoi juste maintenant.
Le dernier paramètre du constructeur vous permets de générer des URI via l’aide de vue Zend_Controller_Action_Helper_Url::url(). En fait, cela revient à l’équivalent du premier paramètre mais non pas en expression régulière mais de manière à être interprété par la fonction PHP sprintf().
Vous pourriez très bien écrire vos URI à la main mais imaginez que vous mettez à jour votre route, allez-vous passer derrière tous vos liens générés et changer manuellement leur pattern ?
L’aide vue Zend_Controller_Action_Helper_Url::url() nous permet de générer des URI automatiquement en lui fournissant le nom de la route (en second paramètre) et les paramètres de l’URI sous forme de tableau en premier paramètre de la méthode.
Nous sommes dans notre script de vue :
1 2 3 4 5 6 7 8 9 | <?php // Nous sommes dans une boucle avec la variable $article_item // Générons une liste de liens permettant d'acceder à l'article courant $uri = $this->url(array( 1 => $article_item->article_year, 2 => $article_item->article_id, 3 => $article_item->article_title_uri ), 'article'); echo '<li><a href="' . $uri . '">' . $article_item->article_title . '</a></li>'; |
Ok, c’est tout pourri comme ça… C’est 10 fois mieux ainsi :
1 2 3 4 5 6 | <?php $uri = $this->url(array( 'article_year' => $article_item->article_year, 'article_id' => $article_item->article_id, 'article_title_uri' => $article_item->article_title_uri ), 'article'); |
Beaucoup plus clair n’est-ce pas ? Ainsi on peut même générer le tableau de manière automatique avec Zend_Controller_Router_Route_Regex::getVariables() qui retourne le contenu du 3ème argument du constructeur.
La ça commence sérieusement à devenir intéressant…
Nous allons en profiter :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <?php class ArticleController extends Zend_Controller_Action { public function init() { } public function indexAction() { $this->view->route_variables = Zend_Controller_Front::getInstance() ->getRouter() ->getRoute('article') ->getVariables(); } } |
Et dans notre script de vue :
1 2 3 4 5 6 7 8 9 10 11 | <?php // Nous sommes dans une boucle avec la variable $article_item // Générons une liste de liens permettant d'acceder à l'article courant // Nous allons associer les valeurs de l'article courant directement avec les clés de la route $article_uri_values = array( $article_item->article_year, $article_item->article_id, $article_item->article_title_uri ); $uri = $this->url(array_combine($this->route_variables, $article_uri_values), 'article'); echo '<li><a href="' . $uri . '">' . $article_item->article_title . '</a></li>'; |
Et encore, on pourrait même pousser le vice à automatiser cette tâche dans notre objet $article_item via une méthode Article::generateUri(). Laissez libre cours à votre imagination
.
Pour en finir…
Si vous avez tout suivi, vous devriez facilement arriver à gérer et générer de manière très propre des routes aussi complexes soient-elles. Pour en finir avec notre bootstrap, voici ce qu’il devrait contenir pour ajouter la route article :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <?php class Bootstrap extends Zend_Application_Bootstrap_Bootstrap { protected function _initRouter() { // Récupère l'instance courante du router actuel si il existe sinon en créer un $router = Zend_Controller_Front::getInstance()->getRouter(); // Défini la route 'article' $route = new Zend_Controller_Router_Route_Regex('article/(\d+)-(\d+)-([-\w]+)\.html?', array( 'controller' => 'article', 'action' => 'index' ), array( 1 => 'article_year', 2 => 'article_id', 3 => 'article_title_uri' ), 'article/%s-%s-%s.html'); // Ajoute la route au router et renvoi l'objet $router->addRoute('article', $route); return $router; } } |
Félicitations, vous venez de comprendre en 15 min mes 2 jours de recherche sur le router du Zend Framework ! Si vous avez des soucis, n’hésitez pas à laisser un commentaire :p.

Il y a également Zend_Controller_Router_Route qui permet de faire des routes sympa de manière un petit peu plus lisibles.
Pour ta dernière, cela donnerait :
En effet, pour l’exemple précédent, c’est pas utile d’utiliser des expressions régulières, une route simple suffit car les valeurs numériques sont en début d’URI mais si on inverse, cela devient plus complexe.
Merci pour ta participation Damien.
Bonjour et merci pour le tuto,
j’ai une question à propos de l’utilisation de Zend_route et du multi-lingue
j’intialise mes routes dans mon bootstrap, j’ai une fonction _initRoute qui en gros va lire un fichier xml dans lequel mes paramètre de routes sont défini, puis loop sur chaque route et les ajouter à zend_router.
je prend ici l’exemple de deux routes que je veux définir, elle pointent vers le même action/controller, mais doivent définir une langue différent
login.html doit pointer vers la le controller login action index, inscription.html doit faire pareil mais avec le paramètre de langue en francais.
voilà ma définition de route en anglais
et celle en francais
dans mon bootstrap j’ai aussi une methode setLanguage($codelangue) qui recoit donc mon code de langue et change la langue à utiliser.
Pourriez vous m’éclaire sur le comment passer le paramètre de langue à ma route, et comment, lors du chargement de ma page (quelque par dans al bootstrap je suppose) faire en sorte de pouvoir utiliser le paramètre de langue précisé dans la route pour le passer à setLanguage()
P-e faire quelque chose dans ce genre la (mais je ne sais pas quelle synthaxe utiliser dans mon boostrap pour récupérer la langue)
merci d’avance
Désolé de revenir avec ca hein, mais j’ai tjrs pas trouvé de solution.
donc en gros j’ai un fichier xml qui défini des roules (avec
- nom à afficher
- controller
- action
- langue
et j’aimerai que le paramètre de langue soit pris en compte par zend_route (sans devoir passer dans l’url)
donc que par exemple si j’ai (via l’xml)
Nom : inscription
Controller : login
Action : index
Langue : fr
et
Nom : register
Controller : login
Action : index
Langue : en
inscription.html pointe vers login/index en francais
et
register.html pointe vers login/index en anglais
j’ai essayé comme précisié dans le code du post précédent, mais quand j’utilise la finction assemble, ca ne prend pas la langue en compte
merci
@Lo : oui merci j’avais très bien compris ton problème mais si je n’ai pas répondu c’est peut-être tout simplement parce que je ne sais pas.
Je m’y pencherais volontier mais pour l’instant, je suis plutôt occupé.
N’hésites pas à fournir l’URL de cette page si tu dois de nouveau expliquer ton problème à d’autres personnes…
Bon courage
http://framework.zend.com/manual/en/zend.controller.router.html#zend.controller.router.routes.standard.translated-segments
tout est expliqué ici
Juste un « @ » à rajouter dans la route.
++ et merci pour l’article.
Farf