URL Rewriting souple : les routes de CakePHP

CakePHP offre une réelle souplesse dans la gestion de l’URL Rewriting à condition d’utiliser des “routes” et de toujours définir les liens de la même façon.

Imaginons un catalogue de produits : nous créons une table “references”, un Modèle “Reference” et un Contrôleur “ReferencesController”. Ce Contrôleur contient l’action “voir” qui prend en paramètre l’id d’une référence et affiche la fiche produit. L’url pour accéder à la fiche produit dont l’id est 5 : /references/voir/5.

Dans une Vue, par exemple la liste des produits, nous avons :

1
2
3
4
5
6
7
8
9
foreach($references as $reference)
{
  e(
    $html->link(
      $reference['Reference']['nom'],
      '/references/voir/'.$reference['Reference']['id']
    )
  );
}

Nous aimerions une url plus élégante, par exemple : /produit/5. Or il n’existe pas de Contrôleur “ProduitsController”, et il n’y a apparemment pas d’action définie. Nous définissons alors une “route” dans le fichier /config/routes.php :

1
2
3
4
5
6
7
Router::connect(
  '/produit/*',
  array(
    'controller' => 'references',
    'action' => 'voir'
  )
);

Ainsi, toute url commençant par “produit/” sera renvoyée sur l’action “voir” du Contrôleur ReferencesController, avec l’id en paramètre.

Nous changeons la vue qui liste les références :

1
2
3
4
5
6
7
8
9
foreach($references as $reference)
{
  e(
    $html->link(
      $reference['Reference']['nom'],
      '/produit/'.$reference['Reference']['id']
    )
  );
}

Et nous finissons notre site en utilisant toujours ce type d’url pour pointer vers une fiche produit.

Maintenant, nous préférerions que l’url soit de la forme : /catalogue/reference/5. Nous changeons la route :

1
2
3
4
5
6
7
Router::connect(
  '/catalogue/reference/*',
  array(
    'controller' => 'references',
    'action' => 'voir'
  )
);

Mais nous devons alors changer tous les liens de nos vues qui pointent vers une fiche produit !

La solution est de toujours définir un lien en passant en paramètre à la fonction link() non pas une chaine de caratère (l’url telle que nous la voulons au final) mais un tableau associatif comme suit :

1
2
3
4
5
6
7
8
9
10
11
12
13
foreach($references as $reference)
{
  e(
    $html->link(
      $reference['Reference']['nom'],
      array(
        'controller' => 'references',
        'action' => 'voir',
        $reference['Reference']['id']
      )
    )
  );
}

De cette façon, l’url affichée dans le lien en sortie reflètera toujours la route définie dans routes.php, quelle qu’elle soit.

Pierre-Emmanuel Fringant

Participez