Optimiser les URL pour le référencement
Nous allons voir comment générer facilement des suffixes d’URL optimisés pour le référencement. Prenons l’exemple d’un catalogue de produits. Par défaut, une URL que CakePHP va produire pour une fiche produit va ressembler à ceci : /produits/view/12 (le nom du Contrôleur, le nom de l’action et l’id du produit à afficher). Nous aimerions qu’elle soit plutôt de la forme /article/12/Livre-de-recettes.
1. Génération du suffixe dans les Vues
Voyons d’abord comment définir les liens vers nos fiches produits, par exemple dans la liste des produits, soit l’action index du Contrôleur Produits.
Nous allons utiliser la méthode statique Inflector::slug() qui prend en paramètre :
- une chaîne de caractères et la retourne exempte de tout caractère “interdit” dans une URL (accents, espaces, ponctuation) ;
- éventuellement un caractère séparateur, l’underscore _ par défaut.
// {app}/views/produits/index.ctp <ul> <?php foreach($produits as $produit): ?> <li> <?php echo $html->link( $produit['Produit']['nom'], array( 'controller' => 'produits', 'action' => 'view', 'id' => $produit['Produit']['id'], 'suffixe' => Inflector::slug($produit['Produit']['nom'], '-') ) ); ?> </li> <?php endforeach; ?> </ul>
Nous obtenons une URL du style : /produits/view/12/suffixe:Livre-de-recettes. Nous progressons, mais nous voulons changer le mot “produits” en “article”, supprimer le nom de l’action, qui n’apporte rien, et le mot “suffixe:” qui n’est pas des plus esthétiques. Pour y parvenir, nous allons tirer parti de la puissance des Routes.
2. Une route personnalisée
Rendons-nous dans le Router :
// {app}/config/routes.php Router::connect( '/article/:id/:suffixe', array('controller' => 'produits', 'action' => 'view'), array('id' => $ID, 'suffixe' => '[a-zA-Z0-9_-]+') );
Voyons un peu les trois arguments que nous donnons à la méthode Router::connect() :
'/article/:id/:suffixe': c’est le format d’URL que nous attendons ;array('controller' => 'produits', 'action' => 'view'): lorsque le Router va reconnaître une URL ressemblant à notre premier argument, il devra renvoyer sur l’action view du Contrôleur Produitsarray('id' => $ID, 'suffixe' => '[a-zA-Z0-9_-]+'): nous définissons ce que nous entendions dans le premier argument par “:id” et “:suffixe” :$IDcontient une expression régulière prédéfinie dans le cœur de Cake, correspondant à un ou plusieurs chiffres ;'[a-zA-Z0-9_-]+'est l’expression régulière que nous définissons pour que le Router reconnaissent nos suffixes d’URL : ce suffixe peut contenir des lettres minuscules ou majuscules, des chiffres, des underscores ou des tirets.
Rafraîchissons notre page /produits/index, et nous constatons que nos URL sont bien de la forme /article/12/Livre-de-recettes !
3. Contrôler la validité d’un suffixe d’URL
Mais que se passe-t-il si un visiteur poste un lien vers notre site dans un forum, et qu’il tronque le suffixe, ou le modifie ? Cela va pénaliser le référencement de la page ciblée, car les moteurs de recherche vont enregistrer plusieurs URL pointant vers la même page : la bonne (/article/12/Livre-de-recettes) et les éventuelles mauvaises (/article/12/Suffixe_incorrect, /article/12, etc.).
Pour pallier à cette éventualité, nous devons nous assurer que le suffixe de l’URL qui arrive est bien celui attendu. Nous allons effectuer un petit contrôle dans l’action view du Contrôleur Produits :
// {app}/controllers/produits_controller.php function view($id = null, $suffixe = '') { $produit = $this->Produit->read(null, $id); // Produit inexistant : erreur 404 if(empty($produit)) { $this->cakeError('error404', array(array('url' => $this->action))); } // Suffixe incorrect : redirection 301 vers la bonne URL $suffixe_attendu = Inflector::slug($produit['Produit']['nom'], '-'); if($suffixe != $suffixe_attendu) { $this->redirect(array('id' => $id, 'suffixe' => $suffixe_attendu), 301); } $this->set(compact('produit')); }
Ainsi nous nous assurons que toute URL mal formée sera redirigée vers la bonne URL avec un code HTTP 301 : ce code va forcer les moteurs de recherche qui suivront les liens, éventuellement mal formés, vers cette page, à ne prendre en considération que la bonne URL.
Commentaires
23 octobre 2008 à 9:05
[...] Optimiser les URL pour le référencement [...]
23 octobre 2008 à 23:30
Bonjour,
Encore un article intéressant, cependant pourquoi garder l’id de l’article dans l’url ?
Ne serait-ce pas plus “beau” et simple d’utiliser une adresse de type : /article/Livre-de-recettes
Il suffirait ensuite d’utiliser :
$produit = $this->Produit->findBySlug($slug);
Aussi, y a-t-il des problèmes à utiliser le Sluggable Behavior ? (http://bakery.cakephp.org/articles/view/slug-behavior)
24 octobre 2008 à 7:33
Je préfère garder l’id au tout début de l’url pour pallier à tout risque d’URL tronquée. Si celle-ci ne comporte que le suffixe, on arrive directement sur une 404. En ayant l’id au début, même si l’URL est incomplète, on peut retrouver le bon enregistrement.
Aucun souci pour utiliser l’excellent SlugBehavior, qui donne la possibilité de contrôler plus finement le suffixe lui-même, par exemple en permettant de le modifier dans le formulaire d’édition de l’enregistrement, ce que ne permet pas ma méthode “rapide”.
19 novembre 2008 à 16:13
Au passage, la méthode Inflector::slug est beaucoup plus limitée en matière de conversion de caractères exotiques que celle présente dans le SluggableBehavior (qui me semble fortement empruntée à Wordpress, d’ailleurs… sinon il y a aussi la méthode d’un collègue : http://pwet.fr/blog/generer_des_url_significatives_en_php).
Autre chose, concernant les id : outre les raisons données par Kalt, il y a celle que j’évoquais dans mon article (là : http://cherryonthe.popnews.com/2008/03/15/basic-seo-and-cakephp-part-1/) sur le sujet, à savoir le référencement sur Google News (ok, c’est un besoin assez spécifique, pas nécessairement applicable à un blog) :
http://www.google.com/support/news_pub/bin/answer.py?answer=68323&topic=11665
12 janvier 2009 à 8:29
Salut,
Belle utilisation de Router…
Par contre, je n’arrive pas à utiliser le Helper paginator avec.
Mon URL est Séries/1/Un_titre
Mais les séries ont des épisodes donc je fais un paginate sur les épisods de la série.
Et en bas de ma page quand je mets
$paginator->numbers() je me retrouve avec des URL du type series/view/page:xx
Donc perte de l’id et du titre de la série et donc pas Série/1/Un_titre/page:2
ps : les accents ça passe
, mais il faut les remplacer par leur équivalent dans le router.
ex : Série => S%C3%A9rie (dans routes.php)
12 janvier 2009 à 8:47
Avant l’appel à
$paginator->numbers();, tu dois passer les paramètres de l’url au paginator en faisant ceci :D’autre part, je te conseille d’enlever les accents des url, c’est quand même plus lisible.
13 mai 2009 à 22:19
En utilisant l’exemple tel que montré ici, les valeurs d’id et de suffixe dans l’action view étaient toujours vide.
En cherchant j’ai trouvé la solution à mon problème, suffit d’ajouter ceci au début de l’action: