URLs amigables (jugando con mod_rewrite)
lunes, 27 de febrero de 2006De lo que se viene en llamar WEB 2.0 (me gusta más el termino de Web Social), probablemente las URL amigables sean la parte que más nos faciliten la vida y mas disfrutemos.
¿Que es una URL amigable? Es facil. Tradicionalmente, cuando solicitamos a una pagina que nos muestre una determinada información, lo que hacemos es asignar una serie de valores a una serie de variables. Estas variables son pasadas a la página a traves de la URL, la pagina las lee, procesa y muestra la información solicitada.
Por ejemplo: Si solicitamos a Google páginas en las que aparezca el término «miserable«, lo que hacemos es asignar a la variable llamada «q» el valor «miserable» y enviarselo a Google tal como: http://www.google.es/search?q=%22miserable%22
Si además queremos que la busqueda se limite páginas en español, asignamos la variable «meta» el valor «lr=lang_es»
http://www.google.es/search?q=%22miserable%22
&meta=lr%3Dlang_es
(los caracteres especiales como comillas, espacios, signo igual, deben ser traducidos).
Todo muy bien, muy claro. Sinembargo conforme las paginas iban admitiendo más y más variables con las cuales filtrar la información a mostrar, el resultado son URL extremadamente largas, incomodas de manejar y no digamos de memorizar. La usabilidad de dichas URLs se aproxima a cero. Por ejemplo, sin ir más lejos hace unos dias me pasaron una dirección a un concurso de infografia, esta es la dirección:
http://www.sicarm.es/servlet/integra.servlets.ServletLink?
sit=c%7C545%7Cm%7C2076%7C&cad=Reportajes
Portal$$Programa$8273$DETALLE_REPORTAJESPADRE$%7
CReportajesPortal$Animaci%F3n%20Digital$8273$
DETALLE_REPORTAJESPADRE$%7CReportajesPortal$Programa%20
(Animaci%F3n)%20-%20Zona%20de%
20Exposici%F3n$9219$DETALLE_REPORTAJESABUELO
De tan larga, tuve hasta problemas para copiar la dirección desde Gaim (si os interesa el concurso, haced Clik AQUI).
A lo ibamos, si se quería hacer una Web intuitiva, lógica y accesible había que solucionar esto y aqui es donde entra un fabuloso módulo que usan los servidores Web Apache, mod_rewrite, un modulo ya muy extendido (afortunamente) por todos los servidores Linux y del que hace uso WordPress (y casi todos los sistemas de weblogs) y que con unos muy breves conocimientos podemos hacer uso para facilitarnos la vida (por defecto, WordPress se instala sin hacer uso de las URL amigables ya que todavía algunos servidores Web no tienen esta funcionalidad activa).
Básicamente lo que hace el módulo mod_rewrite es leer la URL requerida por el usuario y «traducirla» a un lenguaje comprensible por la pagina.
Esto tiene una serie de ventajas obvias y otras no tan evidentes:
1/ El mucho más facil recordar una dirección y más intuitivo averiguar otras.
Por ejemplo, en esta web podeis consultar mis comentarios en la dirección: http://www.trebol-a.com/estadisticas/?stats_author=Trebol-A , no hace falta ser un lince para darse cuenta de que basta con cambiar «Trebol-A» para consultar los comentarios de otro usuario:
http://www.trebol-a.com/estadisticas/?stats_author=miguel
http://www.trebol-a.com/estadisticas/?stats_author=monica
2/ Se evitan problemas
Algunos motores de busqueda llevan malamente la indexación de URLs muy largas y/o cargadas con caracteres especiales, o sencillamente se hace casi imposible manejar URL tan largas. Como muestra la dirección del concurso que daba anteriormente. Si tratais de enviarla a alguien por correo, muy probablemente la recibirá mal formateada ya que el programa de correo provocará un salto de linea, con lo cual a quien la reciba le llegará una dirección no-valida.
3/ Se facilita la actualización del sitio
Para acceder a la galería de imagenes de esta web se dirige al navegador hacia http://fotografia.trebol-a.com ó bien http://www.trebol-a.com/photos. Si mañana decido cambiar el sistema de gestión de la galería (actualmente falbum) la dirección permanece invariable, ya que bastaría con corregir el contenido del archivo .htaccess
4/ Se reduce el numero de errores «404:Page Not Found»
Si como en mi caso, has cambiado la estructura de la web recientemente ó bien observas que llegan enlaces mal dirigidos a la web, bastaría con añadir una nueva regla al archivo .htaccess que rediriga las solicitudes a una url válida.
Jugando con .htaccess
Antes de continuar deberias saber que una mala manipulación del archivo .htaccess puede impedir el acceso a tu sitio. Si en tu sitio existe un fichero llamado .htaccess haz una copia de seguridad para recuperarla en caso de error.
El archivo .htaccess se ubica dentro de cada uno de los directorios publicos de tu sitio y en se guardan las reglas y condiciones que se van aplicar a dicho directorio. Desde la solicitud de contraseñas de acceso, el permiso/prohibición para indexar/listar el contenido del directorio ó (la que nos interesa) la «correción» de URLs que se soliciten dentro del directorio.
Abre con un editor de texto tu fichero .htaccess ó crea uno sino existe (el punto delante indica en linux que es un archivo oculto, si estás en Windows probablemente tengas problemas para crear el archivo). Escribe lo siguiente:
<IfModule mod_rewrite.c>
</IfModule>
Entre esas lineas introduciremos las reglas que se ván a aplicar al directorio siempre y cuando el modulo esté activo. Ahora activamos la reescritura y aplicamos una regla simple:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule . /index.php [L]
</IfModule\>
La sintaxis es la siguiente:
RewriteRule url-solicitada url-destino [bandera]
url-solicitada es usualmente una expresión regular, si se cumple continua la ejecución de la regla.
url-destino, dirección hacia donde dirigir el navegador caso de cumplirse la regla.
bandera, condiciona la ejecución de la regla
La regla anterior envia al «index.php» situado en el directorio raiz ( / ) de nuestro sitio cualquier solicitud (.) que llegue al directorio, a continuación la bandera (L) finaliza la ejecucción si la regla se cumple.
Según la regla anterior, cualquier solicitud que llegue al directorio donde se encuentre dicho .htaccess será redirigida a index.php, INDEPENDIENTEMENTE de que el archivo solicitado exista ó no. Es decir, si disponemos de un archivo llamado fotos.php ó avatar.jpg estos serian innaccesible ya que de forma automática el servidor dirige TODO a index.php.
Para evitar esto, deberiamos añadir una condicion a la regla:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . /index.php [L]
</IfModule\>
RewriteCond, si el requerimiento ( %{REQUEST_FILENAME} ) es un fichero innexistente ( !-f ) ejecuta la regla.
Siguiendo esto, podríamos filtrar las entradas a nuestro sitio leyendo los referers de la visita. Asi por ejemplo, si una entrada a nuestro sitio llega con un referer (falso) que contiene (sex|drugs|rock\&roll) lo cual es signo más que probable de spambot lo redirigiremos a otra pagina especial
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_REFERER} (sex) [NC,OR]
RewriteCond %{HTTP_REFERER} (drugs) [NC,OR]
RewriteCond %{HTTP_REFERER} (rock\&roll) [NC]
RewriteRule . http://www.microsoft.com [L]
</IfModule\>
En el caso anterior la bandera [NC] indica que la condicion es no-sensible a mayusculas, trata de igual manera SEX, sex ó Sex.
Para facilitar la vida a nuestras visitas podriamos leer sus solicitudes de documentos, de tal manera:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)(.htm|.html|.php)$ index.php/?s=$1 [NC,L]
</IfModule\>
Según lo anterior, cualquier solicitud de archivo htm, html ó php que se haga y no se encuentre produciría su busqueda automática. Y redondeandolo más:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)(.gif|.jpg|.jpeg|.png|.bmp) http://www.flickr.com/photos/MI-USER-EN-FLICKR/tags/$1/ [NC,L]
RewriteRule ^(.*)(.htm|.html|.php)$ index.php/?s=$1 [NC,L]
</IfModule\>
Segun la anterior regla redirigimos cualquier busqueda infructuosa de archivos de imagen (gif, jpg, jpeg, png ó bmp) a nuestra cuenta flickr, concretamente intentaría mostrarlo en nuestra lista de tags.
Para seguir profundizando en mod_rewrite:
- Pagina oficial
- Lista de directivas y variables en una imagen para imprimir
- Completo tutorial de expresiones regulares
Percewall
#1/ 27 de February/2006 a 08:57:57
Otros comentarios de «Percewall»
Muy interesante el minituto.
Uso desde hace tiempo el mod_rewrite, pero no he profundizado demasiado en el tema y muchas de las cosas que cuentas no las conocia, sabia que existian, pero la vagueria se apodera de mi. Usare lo del spam a ver si asi evito dichosas visitas molestas.
Aparte, creo que en algun sitio lei, que los buscadores (al menos google), indexa mejor los sitios con guion que con barra baja, es decir, cogiendo como ejemplo esta url:
http://www.trebol-a.com/2006/02/27/urls_amigables/
Creo que indexa mejor
http://www.trebol-a.com/2006/02/27/urls-amigables/
Al menos eso tenia entendido.
Trebol-A
#2/ 27 de February/2006 a 15:22:45
Otros comentarios de «Trebol-A»
Pues ni idea, desconocía la diferenciación que comentas entre (-) y (_). De hecho fijate que he corregido la URI del titulo para que no saliese el entreparentesis y lo he puesto con guión bajo, cuando Wordpress usa (-).
Pero vaya, si que dá bastante juego el mod_rewrite, he puesto por aqui algun ejemplo a modo ilustrativo, pero hay algun que otro ejemplo por la web bastante util. Uno de los que quiero implementar en cuanto tenga tiempo es la opción de detectar mediante los referer los terminos buscados en Google que han traido al visitante a la web y colorear su background para destacarlos.
president
#3/ 04 de January/2007 a 07:07:10
Otros comentarios de «president»
men q sustituiste en tu word press para q aparesca _ en vez de - salu222
Jesus Rodriguez
#4/ 04 de March/2007 a 00:21:29
Otros comentarios de «Jesus Rodriguez»
Si, es cierto lo de el guión (_) o (-) yo no sólo lo he leído en varios sitios; hace bastante tiempo que he visto que lo comentan muchos expertos SEO'S.
Es mejor poner las url's con guión (-) que con guión (_).
Saludos.
Charly
#5/ 08 de August/2007 a 12:51:07
Otros comentarios de «Charly»
Recién comienzo con todo esto. A pesar de esta excelente info y otras que hay en la red no logro hacer marchar algo tan simple como esto:
pagina.php?link=auto
Ej:
RewriteRule ^([^/]*)\.html$ pagina.php?link=$1 [L]
He usado los convertidores online le he dado mil vueltas y nada.
Sin embargo, al probar esto dentro de una carpeta funciona pero al hacer clic da página no encontrada.
Alguna "luz" para continuar investigando?
Gracias
Trebol-A
#6/ 08 de August/2007 a 15:57:37
Otros comentarios de «Trebol-A»
Hola Charly, dos cosas:
- mejor usa rutas absolutas, en lugar de "pagina.php" mejor "/pagina.php"
- y el flag QSA
por lo demás, si añades a tu .htaccess
RewriteEngine on
RewriteRule ^([^/]*)\.html$ /pagina.php?link=$1 [QSA,L]
Cualquiera que llegue a tu web buscando "bicicletas.html" será redirigido a "pagina.php?link=bicicletas"
saludos
Charly
#7/ 09 de August/2007 a 19:07:03
Otros comentarios de «Charly»
Hola Trebol-A, gracias por responder.
Practiqué lo que me dices pero sigue sin andar. Mod funciona ya que si pones alguna redirección o reglas para el ancho de banda con imágenes, etc... va bien. Te doy más info a ver si es por otras cosas:
1- El script que genera esas url ej: "pagina.php?link=auto" está escrito en ZEND y no usa BD se sirve de data que almacena en carpetas dentro del root. Tendrá que ver?.
2- Este es otro tipo de url que genera: "pagina.php?link=1&ref=unpais" y el caso es el mismo... no funciona!.
De todos modos agradezco tu tiempo y seguiré probando y buscando y dándome palos.
Gracias, Charly.
Alquiberia
#8/ 01 de May/2008 a 20:24:28
Otros comentarios de «Alquiberia»
Muy buenas. Tengo una pequeña duda.
Tengo implementado el mod_rewrite en mi web:
http://www.alquiberia.es
Pero tengo un problema cuando supero las 9 variables. Todo funciona perfectamente mientras no supere parametros.
Por ejemplo:
Rewriterule ^([^/]+)-([^/]+)/([^/]+)-([^/]+)/([^/]+)-([^/]+)/([^/]+)-([^/]+)\.html$ index.php?$1=$2&$3=$4&$5=$6&$7=$8 [NC,L]
Funciona perfectamente pero si supero las 9 variables falla y mezcla el valor de las variables.
Alguna sugerencia???
Gracias
Trebol-A
#9/ 02 de May/2008 a 09:58:52
Otros comentarios de «Trebol-A»
Claro, el límite es de $9 variables. Con la bandera C (chain) se podrian encadenar varios patrones, pero no lo he hecho nunca y sinceramente antes de hacerlo creo que cambiaría el método para bastarme con 9 parámetros, de lo contrario lo que ganas con la transpariencia de mod_rewrite lo vas a perder en url extra largas.
Podrías reconstruir las url para que en lugar de tomar nombre=>valor tomen solo el valor. De esta manera, en lugar de hacer:
/raiz/tamaño/grande/color/rojo/forma/cuadrada
index.php?$1=$2&$3=$4&$5=$6 ...
harias:
/raiz/grande/rojo/cuadrado/
index.php?tamaño=$1&color=$2&forma=$3 ...
saludos
Alquiberia
#10/ 04 de May/2008 a 18:55:01
Otros comentarios de «Alquiberia»
Gracias por tu respuesta
Te explico brevemente lo que necesito hacer :
Para cambiar los enlaces dinámicos de la web uso preg_replace de esta forma:
function _replace_rewrite($str) {
$entra = array();$sale = array();
$entra[] = '¬index\.php\?lang=([a-z]+)&sec=([a-zA-Z0-9]+)¬';
$sale[] = 'idioma-$1/seccion-$2.html';
$entra[] = '¬index\.php\?lang=([a-z]+)¬';
$sale[] = 'idioma-$1.html';
$str = preg_replace($entra, $sale, $str);
}
Y funciona perfectamente, siempre y cuando el formato de entrada sea igual a los definidos en $entra[].
Si entra: http://www.alquiberia.es/index.php?lang=es&sec=1
, obtengo: http://www.alquiberia.es/idioma-es/seccion-1.html
, después en htaccess lo redirecciono: Rewriterule ^idioma-([^/]+)/seccion-([^/])\.html$ index.php?lang=$1&sec=$2 [NC,L]
Pero si entra http://www.alquiberia.es/index.php?sec=1&lang=es , el preg_replace no cumple su función.
Imagínate esto pero con 14 ó 18 variables, a las que no les puedo dar un formato uniforme ya que se envían unas u otras dependiendo de varios factores.
Mi intención era conseguir que se enviaran las variables que se recibieran de esta forma:
$entra[] = '¬index\.php\?([a-zA-Z0-9]+)=([a-zA-Z0-9]+)&([a-zA-Z0-9]+)=([a-zA-Z0-9]+)¬';
$sale[] = '$1-$2/$3-$4.html';
Rewriterule ^([^/]+)-([^/]+)/([^/]+)-([^/]+)\.html$ index.php?$1=$2&$3=$4 [NC,L]
Esta es la idea básica, pero con un mínimo de 12 parametros y un máximo de 18.
Y sólo se usaría en unos pocos enlaces.
Gracias
Trebol-A
#11/ 04 de May/2008 a 21:02:45
Otros comentarios de «Trebol-A»
Claro, ese modo te ata a que las variables te lleguen en el orden esperado. Si no es el caso, como parece estás obligado a parsear la url requerida.
Si por ejemplo te llega: $a="http://www.alquiberia.es/index.php?lang=es&sec=1"
Obtienes el query con:
parse_url($a)
arra=parse_str($a["query"])
Esto te deja en $arra
Array
(
[lang] => es
[sec] => 1
)
A partir de ahí te hace un foreach que comprueba que valores has recibido para reconstruir la url a tu gusto.
Alquiberia
#12/ 05 de May/2008 a 08:39:17
Otros comentarios de «Alquiberia»
Muchas gracias por tu ayuda, esa es la solución. Funciona Perfectamente.
¿Cómo no se me habiá ocurrido? :-0
Un saludo
Ziggy
#13/ 12 de June/2008 a 15:28:58
Otros comentarios de «Ziggy»
Hola, yo estoy empezando con esto y no logro hacer lo más simple: el ejemplo que pones arriba ...
RewriteEngine On
RewriteRule . /index.php [L]
Ya he chequeado que el mod_rewrite está ok y todo eso ...
Ziggy
#14/ 12 de June/2008 a 15:41:47
Otros comentarios de «Ziggy»
Acabo de ver que hubo un tal Charly que tenía el mismo problema que yo, porque también he probado con esa que dices de bicicleta y na de ná ...
Ziggy
#15/ 13 de June/2008 a 12:28:33
Otros comentarios de «Ziggy»
Y otra cosa. Yo lo que quiero es que no me aparezca el superchorizo en la barra de direcciones. Cómo hago para que se cambie automáticamente por lo que quiero sustituir. Es que sólo me funciona si lo hago directamente y lo escribo yo en la barra, pero si hago clic en un enlace, me sigue apareciendo el enlace tal y como es.
Saludos
Ziggy
#16/ 13 de June/2008 a 14:56:17
Otros comentarios de «Ziggy»
ACLARACIÓN IMPORTANTE: mod_rewrite no reescribe la url en la barra del navegador. Esto lo hacemos nosotros. Lo que hace mod_rewrite es traducir esa url amigable que nosotros usamos en nuestros enlaces, por la “url dinámica real” que cargará el contenido correspondiente usando php y mysql (o la tecnología del servidor en cuestión).
Miradlo aquí: http://www.linkalicante.com/activar-mod_rewrite-en-apache/
Madre mia!
#17/ 02 de July/2008 a 18:07:44
Otros comentarios de «Madre mia!»
Gracias Ziggy!
Y yo constantemente mirando la URL del navegador jaajajajajaja XD ke pinza!!!
Tendre que informarme más.
Gracias de nuevo por abrirme los ojoos jaja XD
Salu2
Genial Blog Trebol!
Zerf
#18/ 01 de September/2008 a 12:15:43
Otros comentarios de «Zerf»
Muy interesante y aclarador el artículo. Mi problema es que hizo hace mucho el tema de las URL... y no lo hice bien del todo. Por ejemplo, utilicé _ y le di demasiada profundidad a los enlaces.
Mi pregunta es... ¿hay alguna forma de cambiar ahora? ¿Se enfadará Google conmigo? :s
Juan Antonio
#19/ 03 de September/2008 a 05:25:17
Otros comentarios de «Juan Antonio»
Jaja me contesto yo mismo, como no podia esperar me puse a analizar la sentencia y cambie al ultimo la f por una d y jalo jeje, ya lo cheque en el manual y es correcto "RewriteCond %{REQUEST_FILENAME} !-d" logico no?? f = file, d= directory.
Mediterranean Adobe User Group » Blog Archive » Instalando MySQL4+PHP4+Apache2
#20/ 10 de December/2008 a 23:43:45
Otros comentarios de «Mediterranean Adobe User Group » Blog Archive » Instalando MySQL4+PHP4+Apache2»
[...] trebol-a [...]
Anonimo
#21/ 11 de February/2009 a 17:49:49
Otros comentarios de «Anonimo»
Hola!
He visto en muchas web que manejan el tema de mod_rewrite.
Pero lo que me llama la atención es que cuando se introduce tipo
articulo.php?id=3 automaticamente se cambiar a una URL amigable.
¿Cómo se puede hacer esto? es un header location o algo parecido.
aldisa
#22/ 05 de November/2011 a 20:22:09
Otros comentarios de «aldisa»
como hago para hacer amigable lo siguiente url disculpe estube intentando y me salia error 500 Internal server Error
/detalle.php?idprod=338&TB_iframe=true&height=390&width=700
Saludos
Aleksander R. Salinas Caldas
Juan
#23/ 17 de January/2012 a 00:27:49
Otros comentarios de «Juan»
Hola he seguido los pasos que se dan en este post y funciona de maravilla el problema que tengo es que google no me detecta las paginas y me da error 404
18 de December, 2024 @ 12:34