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

Pour insérer une portion de code, utilisez <pre lang="php">...</pre>