sábado, 5 de enero de 2013

CodeIgniter: URLs SEO-friendly y localizadas


Después de haber visto cómo internacionalizar CodeIgniter utilizando unos archivos de idioma, vamos a ver en este post cómo crear URLs localizadas y SEO-friendly, es decir, URLs explícitas tanto para los motores de búsqueda como para los usuarios.

Limpieza de las URLs predefinidas


De forma predeterminada, las URLs incluyen un llamamiento al archivo index.php: ejemplo.com/index.php/controlador/metodo/parametro

Para obtener una URL más legible como ejemplo.com/controlador/metodo/parametro, vamos a utilizar las reglas siguientes de reescritura de URL de Apache (en el archivo .htaccess).
    .htaccess
    RewriteEngine on
    RewriteCond $1 !^(index\.php|images|robots\.txt)
    RewriteRule ^(.*)$ index.php/$1 [L]
El archivo de configuración (application/config/config.php) también debe ser modificado para indicar la página de índice predeterminada (vacío).
    $config['index_page'] = '';

Internacionalización: controlador y vista localizados


De manera predeterminada, las URLs producidas por CodeIgniter (limpiadas por la reescritura) son de la forma ejemplo.com/controlador/metodo/parametro

Un sitio internacionalizado debe pasar en sus parámetros el idioma de consulta (aquí utilizaremos un código de lengua en dos letras).

El enrutamiento se define en el archivo application/config/routes.php
    // English
    $route['en/my-test/my-view'] = 'test/view/en';

    // Spanish
    $route['es/prueba/vista'] = 'test/view/es';
Se soportan las siguientes URLs:
  • ejemplo.com/en/my-test/my-view/
  • ejemplo.com/es/prueba/vista/
pero también éstas:
  • ejemplo.com/en/my-test/my-view
  • ejemplo.com/es/prueba/vista
Por lo tanto sólo las rutas listadas (las demás siendo devueltas en error 404), pero dos URLs posibles para cada página, una con una barra diagonal al fin, otra sin. Este es el problema del contenido duplicado en varias direcciones que puede acceder a los mismos contenidos.

Ojo: si se cambia una URL durante la vida del sitio, las redirecciones 301 no pueden ser implementadas en el archivo de configuración de enrutamiento sino al nivel del servidor (por ejemplo en el archivo .htaccess).

Recuperación de los parámetros


Para aceptar cualquier parámetro adicional sin saber de antemano su valor, hay que duplicar cada línea añadiendo (:any) que coincidirá por expresión regular con el resto de la URL con la segunda variable del controlador. Como se puede ver en la clase CI_Router (definida en el archivo system/core/Router.php), (:any) es una expresión regular ávida (sustituida por .+ correspondiente a cualquier carácter, incluyendo la barra diagonal). Por tanto, es preferible sustituirla por ([^/]*) (cualquier carácter, excepto la barra diagonal).
    $route['en/my-test/my-view'] = 'test/view/en/';
    $route['en/my-test/my-view/([^/]*)'] = 'test/view/en/$1';
Por otra parte, nos gustaría pasar cualquier número de parámetros a los métodos de los controladores, sin tener que definir por cada ruta el número de parámetros fijos aceptados. La solución anterior sólo recupera el primero parámetro, como una cadena (donde se preferiría una tabla con todos los parámetros).

Para hacer esto, obtendremos la URL completa en el controlador, y luego explotarla en tabla a través del método segment_array.
    class Test extends CI_Controller {
        public function view() {
            $params = $this->uri->segment_array();
Por lo tanto, la URL ejemplo.com/en/my-test/my-view/param1/param2 crea la tabla Array ( [1] => en [2] => my-test [3] => my-view [4] => param1 [5] => param2 )

Su primer elemento es el código de idioma, luego vienen el controlador y la vista localizados (muy útiles si quiere hacer redirecciones), et enfin les paramètres.

Por otra parte, los parámetros recuperados son independientes del enrutamiento, así que podemos volver a una expresión regular ávida.
    // English
    $route['en/my-test/my-view'] = 'test/view/en/';
    $route['en/my-test/my-view/(.*)'] = 'test/view/en/$1';

    // Spanish
    $route['es/prueba/vista'] = 'test/view/es';
    $route['es/prueba/vista/(.*)'] = 'test/view/es/$1';

Resumen


Hemos separado los nombres internos de los controladores y de sus métodos de los nombres externos que aparecen en las URLs, lo cual es beneficioso incluso si el sitio admite un solo idioma. Estamos hablando aquí de internacionalización, ya que todo está listo para que el sitio esté localizado en diferentes lenguas/culturas. El código de idioma aparece antes del nombre localizado del controlador en la URL, dando la ilusión de un subdirectorio específico para cada idioma soportado. Finalmente, el número de parámetros soportado por los métodos de los controladores queda libre en el archivo de rutas, desde que se gestiona directamente en los propios métodos.

Libro


CodeIgniter for Rapid PHP Application Development


Para ir más lejos, recomiendo la lectura de este libro: CodeIgniter for Rapid PHP Application Development, por David Upton (2007, 220 páginas).


CodeIgniter : URLs SEO-friendly et localisées (en francés)
CodeIgniter: SEO-friendly localized URLs (en inglés)
CodeIgniter: URLs SEO-friendly e localizados (en portugués)

No hay comentarios:

Publicar un comentario