Mettre en place le routeur

C'est bien beau tout ça, mais pour l'utiliser, il faut déjà en informer le controlleur. Pour cela, rien de plus simple, on utilise la méthode addRouter:

$router = new Zend_Controller_RewriteRouter;
$controller = Zend_Controller_Front::getInstance();
$controller->setRouter($router);

Le RewriteRouter est pré-configuré avec deux routes qui permettent d'assurer la compatibilité descendante avec l'ancien routeur, donc jusque là, tout va bien.

Déclarer les routes

Nous utiliserons un fichier de configuration dédié aux routes, que nous appellerons sobrement routes.ini, et que nous placerons dans app/, à coté de son compagnon config.ini. Ce fichier de configuration contiendra une unique section [routes], qui contiendra à son tour les multiples définitions de routes que nous souhaitons y caser. Une route se compose de 5 éléments principaux:

  1. L'identifiant de la route. C'est un identifiant interne utilisé par le RewriteRouter,
  2. l'URL de la route, c'est ce qui permet au routeur de reconnaitre la route à utiliser,
  3. les valeurs par défauts des variables,
  4. les requirements de la route, qui permettent de déterminer si une route est bien formée ou non.

Sans plus attendre, un petit exemple: la route qui pourrait permettre d'accéder à un billet dans dotclear 2:

post.route = post/:year/:month/:day/:title
post.reqs.year = "\d+"
post.reqs.month = "\d+"
post.reqs.day = "\d+"
post.reqs.title = "[a-zA-Z0-9_:-]"+
post.defaults.controller = post
post.defaults.action = view
post.defaults.title =

Elle pourrait seulement, car en fait, la regexp du title est trop restrictive (une URL peut contenir d'autres caractères que ceux là), et de plus, les URL stockées par dotclear 2 en base de données comprennent tout ce qui se trouve après post/ (par exemple le champs post_url de ce billet contient: 2006/10/31/Howto:-Utiliser-Zend_Controller_RewriteRouter-avec-Zend_Config).

Cela étant dit, la route que nous venons de décrire s'appliquera aux URLs suivantes:

  • /post/2006/30/10/ZendFramework
  • /post/42/2006/56/Foobar
  • /post/2006/30/10/
  • etc.

Mais pas à:

  • /post/2006/Foobar
  • /post/Foobar/2006/30/01
  • etc.

On note donc d'ores et déjà:

  • que la validation des composants d'une route se fait par expression régulière
  • qu'on peut ommettre le dernier composant d'une route si il possède une valeur par défaut (récursivement)
  • qu'on ne peut pas modifier l'ordre des composants d'une route
  • qu'on doit spécifier manuellement le nom du controlleur et de l'action à utiliser
  • et c'est déjà pas mal.

Décortiquons maintenant une URL: /post/2006/30/10/ZendFramework. Le routeur va diviser cette URL ainsi:

  • Controller: post (d'après les defaults)
  • Action: view (d'après les defaults)
  • Paramètres: year: 2006, month: 30, day: 10, title: ZendFramework (d'après l'URL)

Les paramètres ainsi détectés seront disponibles via la méthode $this->_getParam($name); a l'intérieur du controlleur.

Dernier point de ce chapitre, une déclaration de route peut comporter deux variables spéciales: :controller et :action, qui servent respectivement à détecter le controller et l'action à utiliser dans l'url. Par exemple, la route builtin compat chargé d'assurer la compatibilité descendante se déclare ainsi:

compat.route = :controller/:action
compat.defaults.controller = index
compat.defaults.action = index

Assembler le tout

Dernière étape, transférer directement toutes ces déclarations dans le Routeur: n'y allons pas par quatre chemin:

$router->addConfig(new Zend_Config_Ini('/path/to/routes.ini', null), 'routes');

C'est aussi simple que ça. Ce qui nous donne, en prenant en compte le morceau de code du début de l'article:

$router = new Zend_Controller_RewriteRouter;
$router->addConfig(new Zend_Config_Ini($routes_path, null), 'routes');
$controller = Zend_Controller_Front::getInstance();
$controller->setRouter($router);

And voilà. Je ne saurais que vous conseiller la lecture du manuel pour plus d'informations (sachant qu'en fait, addRoute attend en deuxième argument une instance de Zend_Controller_Router_Route, mais qui s'instancie avec les paramètres qu'ils passent à addRoute, petite coquille du manuel :p).