samedi 5 janvier 2013

CodeIgniter : URLs SEO-friendly et localisées


Après avoir vu comment internationaliser CodeIgniter en utilisant des fichiers de langue, nous allons voir dans ce billet comment créer des URLs localisées et SEO-friendly, c'est-à-dire des URLs explicites à la fois pour les moteurs de recherche et les utilisateurs.

Nettoyage des URLs par défaut


Par défaut, les URLs contiennent un appel au fichier index.php : exemple.com/index.php/controleur/methode/parametre

Pour obtenir une URL plus lisible telle que exemple.com/controleur/methode/parametre, nous allons utiliser les règles de réécriture d'URL d'Apache suivantes (dans le fichier .htaccess).
    .htaccess
    RewriteEngine on
    RewriteCond $1 !^(index\.php|images|robots\.txt)
    RewriteRule ^(.*)$ index.php/$1 [L]
Le fichier de configuration (application/config/config.php) doit aussi être modifié pour indiquer la page d'index par défaut (vide).
    $config['index_page'] = '';

Internationalisation : contrôleur et vue localisés


Par défaut, les URLs produites par CodeIgniter (nettoyées par réécriture) sont de la forme exemple.com/controleur/methode/parametre

Un site internationalisé doit passer dans ses paramètres la langue de consultation (nous utiliserons ici un code de langue en deux lettres).

Le routage est défini dans le fichier application/config/routes.php
    // English
    $route['en/my-test/my-view'] = 'test/view/en';

    // French
    $route['fr/essai/vue'] = 'test/view/fr';
On supporte bien les URLs suivantes :
  • exemple.com/en/my-test/my-view/
  • exemple.com/fr/essai/vue/
mais aussi celles-ci :
  • exemple.com/en/my-test/my-view
  • exemple.com/fr/essai/vue
Donc uniquement les routes listées (les autres étant renvoyées en erreur 404), mais deux URLs possibles pour chaque page, l'une avec une barre oblique finale, l'autre sans. Il s'agit de la problématique du contenu dupliqué où plusieurs adresses accèdent au même contenu.

Attention : lors d'un changement d'URL au cours de la vie du site, les redirections 301 ne peuvent pas être mises en place dans le fichier de configuration du routage mais au niveau du serveur (par exemple dans le fichier .htaccess).

Récupération des paramètres


Pour accepter un quelconque paramètre supplémentaire sans connaître à l'avance sa valeur, il faut dupliquer chaque ligne en ajoutant (:any) qui va matcher par expression régulière le reste de l'URL avec la seconde variable du contrôleur. Comme on peut le voir dans la classe CI_Router (définie dans le fichier system/core/Router.php), (:any) est une expression régulière gourmande (remplacée par .+ qui correspond à n'importe quel caractère, y compris la barre oblique). Il est donc préférable de la remplacer par ([^/]*) (tout caractère, sauf la barre oblique).
    $route['en/my-test/my-view'] = 'test/view/en/';
    $route['en/my-test/my-view/([^/]*)'] = 'test/view/en/$1';
Par ailleurs, nous voudrions pouvoir passer n'importe quel nombre de paramètres aux méthodes des contrôleurs, sans devoir définir pour chaque route le nombre de paramètres fixes acceptés. La solution précédente ne récupère que le premier paramètre, sous forme de chaîne (là où on préfèrerait un tableau de tous les paramètres).

Pour ce faire, nous allons récupérer l'URL complète dans le contrôleur, puis l'exploser en tableau via la méthode segment_array.
    class Test extends CI_Controller {
        public function view() {
            $params = $this->uri->segment_array();
L'URL exemple.com/en/my-test/my-view/param1/param2 créé donc le tableau Array ( [1] => en [2] => my-test [3] => my-view [4] => param1 [5] => param2 )

Son premier élément est le code de la langue, puis viennent le contrôleur et la vue localisés (bien utiles si on veut faire des redirections), et enfin les paramètres.

Par ailleurs, les paramètres récupérés étant indépendants du routage, on peut repasser à une expression régulière gourmande.
    // English
    $route['en/my-test/my-view'] = 'test/view/en/';
    $route['en/my-test/my-view/(.*)'] = 'test/view/en/$1';

    // French
    $route['fr/essai/vue'] = 'test/view/fr';
    $route['fr/essai/vue/(.*)'] = 'test/view/fr/$1';

Récapitulatif


Nous avons séparé les noms internes des contrôleurs et de leurs méthodes des noms externes qui figurent dans les URLs, ce qui est bénéfique même si le site ne supporte qu'une seule langue. Nous parlons donc ici d'internationalisation, puisque tout est prêt pour que le site soit localisé dans différentes langues/cultures. Le code de la langue est passé devant le nom localisé du contrôleur dans l'URL, donnant l'illusion d'un sous-répertoire spécifique pour chaque langue supportée. Enfin, le nombre de paramètres supportés par les méthodes des contrôleurs est laissé libre dans le fichier de routage, puisque géré directement dans les méthodes elles-mêmes.

Lecture


CodeIgniter for Rapid PHP Application Development


Pour aller plus loin, je vous conseille la lecture de cet ouvrage : CodeIgniter for Rapid PHP Application Development, par David Upton (2007, 220 pages).


CodeIgniter: SEO-friendly localized URLs (en anglais)
CodeIgniter: URLs SEO-friendly y localizadas (en espagnol)
CodeIgniter: URLs SEO-friendly e localizados (en portugais)

Aucun commentaire:

Enregistrer un commentaire