URL amigables genéricas
21 de September, 2007
Las URL amigables se están usando hace ya bastante tiempo, consiste en acortar las URL y hacerlas lo mas “humanas” posibles. ¿Para qué? estética, optimizacion para buscadores, lograr URL mas fáciles de recordar, etc. Con ésta técnica intentamos pasar de una url como la que sigue:
www.example.com/index.php?categoria=15&pagina=3&orden=asc
A una como esta:
www.example.com/categoria/15/pagina/3/orden/asc
o bien:
www.example.com/15/3/asc
¿Cómo se logran?
Depende con que servidor trabajes. Si trabajas con Internet Information Server (IIS) podrás lograrlas con ISAPI_Rewrite entre otros. Si trabajas sobre APACHE, podrás lograrlas a través de un fichero .htaccess solo si tenés activado mod_rewrite.
Seguramente haya algunas alternativas más, yo solo conozco estas.
En este artículo explicaré como hacerlo con APACHE, mod_rewrite y un .htaccess (mas un poco de ayuda de PHP, claro), usando un archivo index.php como receptor de todas las peticiones, tal como sucedía en el sencillo ejemplo de mvc que comente el otro día.
Probando el .htaccess
El .htaccess de prueba(y definitivo) que debes usar es el siguiente:
<ifmodule mod_rewrite.c>
RewriteEngine On
#Si la url solicitada no es un fichero(existente), continuar...
RewriteCond %{REQUEST_FILENAME} !-f
#Si la url solicitada no es una carpeta(existente), continuar...
RewriteCond %{REQUEST_FILENAME} !-d
#se toma todo ese -query_string- y se pasa como parametro route
RewriteRule ^(.*)$ index.php?route=$1 [L,QSA]
</ifmodule>
Y un archivo .php para probar:
1 | < ?php echo $_GET['route']?> |
Estos dos archivos los podrias subir a un directorio-de-prueba de tu sitio y la url para probar si todo funciona seria:
www.tusitio.com/directorio-de-prueba/esto/funciona/bien
Si se imprime por pantalla “esto/funciona/bien” estas de suerte, todo está perfecto, de lo contrario, al final del artículo te doy algunas opciones.
Recuperando las variables de la URL
Como habrás visto en el ejemplo, la gracia es que todas esas variables que intentamos pasar como si directorios fueran, quedan almacenadas en una variable GET (de las de verdad) llamada route gracias a la tarea que realiza el .htaccess y el mod_rewrite. Ya sabes donde están las variables, ahora tenes que decidir como las vas a usar.
Nombre – Valor
Si vas a pasar por URL el nombre de la variable y su correspondiente valor tal como en el siguiente ejemplo:
www.example.com/categoria/15/pagina/3/orden/asc
El contenido de tu index.php deberá ser algo como lo que sigue:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | < ?php function getVariables($url) { //quitamos la barra del final $url = preg_replace('/\/$/', '', $url); //separamos las partes de la url y las contamos $partes = explode('/', $url); $cantPartes = count($partes); //si la cantidad de partes no es par retornamos false, al ser impar una variable se quedaria sin valor y esto no es posible if($cantPartes % 2 != 0) return false; $variables = array(); for($c = 0; $c < $cantPartes; $c = $c + 2) { //Acumulamos los pares de valores(para nosotros variables) en el arreglo $nombre = limpiar($partes[$c]); $valor = limpiar($partes[$c + 1]); $variables[$nombre] = $valor; } return $variables; } function limpiar($valor) { //permitimos solo letras(a-Z), numeros y guiones return preg_replace('/[^a-zA-Z0-9-_]/', '', $valor); } $_GET = getVariables($_GET['route']); if($_GET) { echo '< pre>'; print_r($_GET); echo '< /pre>'; }else{ echo 'No hay variables GET'; } ?> |
Ejemplo en mi sitio: urls-genericas/valores/mivariable/valor/otravariable/otrovalor
1 2 3 4 5 | Array ( [mivariable] => valor [otravariable] => otrovalor ) |
Solo valores
Si con el ejemplo anterior te parece que la URL queda muy larga, podés quitar el nombre de las variables y recibir los valores como un simple arreglo. Eso si, debes tener mucho cuidado de ser ordenado y mantener un orden en los parámetros o te harás un lió.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | < ?php function getVariables($url) { //quitamos la barra del final $url = preg_replace('/\/$/', '', $url); //separamos las partes/variables de la url y las contamos $variables = explode('/', $url); $cantVariables = count($variables); for($c = 0; $c < $cantVaraibles; $c++) { //Acumulamos los valores en un arreglo $variables[$c] = limpiar($variables[$c]); } return $variables; } function limpiar($valor) { //permitimos solo letras(a-Z), numeros y guiones return preg_replace('/[^a-zA-Z0-9-_]/', '', $valor); } $misVariablesGet = getVariables($_GET['route']); if($misVariablesGet) { echo '< pre>'; print_r($misVariablesGet); echo '< /pre>'; }else{ echo 'No hay variables GET'; } ?> |
Ejemplo en mi sitio: urls-genericas/valores/valor/otrovalor
Array
(
[0] => valor
[1] => otrovalor
)
A tener en cuenta
Por las reglas que pusimos en nuestro .htaccess estamos pidiendo que todo “query_string” que no exista(lo que comúnmente arroja un error 404) sea dirigido a nuestro index.php. Es necesario que lo tengas en cuenta, porque si entro a tu sitio y busco un fichero que no existe, seré redirigido a tu index.php (inténtalo en mi blog, verás donde eres redirigido). Aprovecha esto para hacer una página de error 404 personalizada para tus usuarios, como la de mi blog por ejemplo.
Por otro lado, si pretendes utilizar una URL como misitio.com/seccion/3 es necesario que tengas en cuenta que para que te llegue la variable sección a tu index.php no debería haber ningún directorio con dicho nombre o lo que veras es el contenido de ese directorio y no tu index.php
¿Por qué en el titulo dice URL genéricas?
Intentaba expresar que era un mini sistema que funciona para cualquier numero de variables, sin necesidad de andar cambiando el fichero .htaccess a cada momento.
¿Es todo?
Por ahora si. Tené en cuenta que es un simple ejemplo y de seguro se puede mejorar. Por lo pronto yo mejoraría un poco el filtro(función limpiar y demas) ya que lo que hace actualmente es borrar caracteres no deseados cuando en realidad debería arrojar un error 404 o similar. La idea es que no haya varias URL diferentes apuntando al mismo contenido, podés leer mas sobre el tema buscando sobre posicionamiento en buscadores.
Podés descargar los ficheros para probarlos desde aquí.
Problemas al usar .htaccess
Si al subir el .htaccess y probarlo te tira un error es probable que no tengas activado el mod_rewrite o tu host no te permite utilizar ficheros .htaccess, contacta con el soporte técnico pero mientras tanto borra el fichero para que no siga tirando error. En algunos hosts cuando subes el archivo .htaccess, este desaparece o se oculta, en este caso si te tira error y no podes borrar el fichero porque no lo ves, sube otro .htaccess vacio para que sobrescriba el anterior.
Si estás trabajando en tu servidor local y tenés problemas es muy probable que los soluciones editando el archivo httpd de apache/conf y habilitando el mod_rewrite, debes descomentar la linea que dice #LoadModule rewrite_module quitandole el # que lleva por delante. Si usas XAMPP, ImZyos te explica como habilitarlo. Si usas WAMP5, creo que te alcanza con acceder al menú->apache_modules->rewrite_module.
Otros artículos
31 comentarios en “URL amigables genéricas”
Deja tu comentario
El blog funciona con Wordpress y Simpla theme

September 21, 2007 a las 4:24 am
Jejeje, bien, yo puse un post en mi blog, pero es de risa al lado del tuyo ^^ exelente trabajo Federico
September 21, 2007 a las 4:53 am
yo dejo mi función haber si a alguien le sirve:
extract(getVars());
function getVars()
{
$vars = explode(‘/’, preg_replace(‘/\/$/’, ”, $_GET['route']));
foreach($vars as $value)
$var[$value] = $value;
return $var;
}
September 21, 2007 a las 8:08 am
Hola ImZyos!
Parece mas sencillo tu código, de hecho no me explico por que use for en lugar de foreach
Lo único que cambiaría es que a extract le agregaría el parámetro EXTR_SKIP para que no sobrescriba variables existentes, por las dudas ya sabes jeje.
Saludos!
September 21, 2007 a las 10:51 am
Muy buen post…
September 21, 2007 a las 11:38 am
Jajaja, bueno eso si, en general yo me brinco la seguridad de mis funciones por algo simple, yo las mando a llamar, asi qeu si hay error sera mio por sobre escribir una variable duplicada, pero ya esta hecho el cambio ^^, gracias por el link.
October 8, 2007 a las 1:22 pm
Pues yo lo he probado, y para lo que quiero, me funciona sin problemas.
Lo único que he tenido mas quebraderos de cabeza, han sido los caracteres especiales, ya que, si pasaba en la variable $_GET['route'] algún caracter inválido (la ñ, los acentos óáè o caracteres especiales como ¿¡!?) no los codificaba bien, con lo que he tenido que usar la función urlencode() de php para solventar el problema (la cual, no había usado hasta ahora :p)
Gracias por el aporte compañero!
October 8, 2007 a las 1:37 pm
Hola DooBie, gracias por compartir el inconveniente y solución.
La otra es hacer como me parece que hace WordPress, convierte las ñ en n, los acentos los pasa de é a e y borra todos los caracteres especiales.
Saludos
April 1, 2008 a las 10:12 am
Excelente articulo!!! me fue de mucha utilidad, lo unico que tuve que modificar en el .htaccess fue la siguiente linea:
RewriteRule ^(.*)$ index.php?route=$1 [L,QSA]
por
RewriteRule .* /index.php?route=$1 [L,QSA]
Me estaba dando un error 500 y de esa forma ya no sucede.
Gracias!
April 1, 2008 a las 10:16 am
Perdón, de esa forma no me pasaba la variable, la forma correcta es:
RewriteRule ^(.*)$ /index.php?route=$1 [L,QSA]
Saludos!!!
April 1, 2008 a las 2:00 pm
Hola Daniel, gracias por compartirlo, de seguro le servira a alguien mas.
July 5, 2008 a las 12:34 am
Muy bueno el post gracias
July 10, 2008 a las 7:44 am
bacan todo pero como se podria hacer esto de las variables amigables primero con varios archivos no solo el index.php es decir que recoja con otros archivos los valores, por ejemplo http://misitio/usuarios.php/user/2345.
Así de lo anterior recojera variable user=2345
Gracias de antemano por su respuesta..
July 10, 2008 a las 11:26 am
muy buen post! no lo habia visto
gracias por la info!
July 24, 2008 a las 6:25 pm
exelente POST de verdad muy bueno, hata ahora visito tu blog y esta m,uy bueno… sigue asi te felicito
July 29, 2008 a las 3:26 pm
Mi web experimento cambios en el diseño, no carla las imagenes, que pudo ser???
July 29, 2008 a las 3:31 pm
Hola andreco, gracias por el comentario. Creo que olvide mencionarlo, pero seguro el problema se debe a la falta del tag base que debes agregar cuando utilizas url amigables.
Referencia: Tag base
Con este tag debes indicar el directorio raiz de tu sitio, para que asi pueda encontrar las carpetas/imagenes.
Un saludo
July 29, 2008 a las 4:23 pm
entiendo ahora el saunto es: para cargar css??? y cosas de este estilo, hay mas especificaciones??????
July 29, 2008 a las 4:27 pm
Andreco, es el tag base solamente, no entiendo como se me pasó!
Y cuenta tanta para las imagenes como para los estilos.
Si tu url es http://www.sitio.com/index.php, el tag base deberia contener:
http://www.sitio.com/
Saludos
July 29, 2008 a las 4:35 pm
asi lo tengo yop
RewriteEngine On
#Si la url solicitada no es un fichero(existente), continuar…
RewriteCond %{REQUEST_FILENAME} !-f
#Si la url solicitada no es una carpeta(existente), continuar…
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?route=$1 [L,QSA]
pero no se , es muy extrano la web no carga la imagende fondo y la capa css, estoy dandole por todo lado y nada que puedo..
July 29, 2008 a las 6:40 pm
Pasame un link y veo si te puedo ayudar. Si queres usar el formulario de contacto.
Saludos
August 20, 2008 a las 1:05 am
si tienes problemas con las rutas de la imagen o css
por haber puesto : /images/tuimagen.jpg (ejemplo)
debes de reemplazarlo por la ruta completa :
http://tuwebsite.com/images/tuimagen.jpg
Suerte..
September 17, 2008 a las 4:41 am
Te felicito es de lo mas claro que he encontrado!
saludos y gracias
February 19, 2009 a las 5:19 pm
Pues comento que el tag base solo sirve para imagenes y links mas no para las imagenes de fondo.
Saludos,
Muy buen Post
February 19, 2009 a las 5:43 pm
jaja, lo siento, error mio… si funciona….
March 18, 2009 a las 12:25 pm
Hola, el ejemplo es genial, mi enhorabuena, pero yo tengo la necesidad de implantar esto no solo en el index, tambien en otras paginas aparte de la raiz como por ej. articulo.php?id=xx
Lo he probado pero no funciona, supongo que será cambiando el script del lado php. Alguna sugerencia? Saludos y gracias de antemano, habeis hecho un buen trabajo.
June 2, 2009 a las 1:08 pm
cual seria el codigo en el .htaccess para transformar la url http://www.misitio.com/pagina.php?id=5&seccion=noticias&titulo=lomejor a http://www.misitio.com/pagina/5/lomejor, osea sacar la variable seccion
February 20, 2010 a las 11:35 am
Hola soy muy nuevo en esto, eh probado tu script y realmente me he quedado con una duda.
URL: http://metrics2b.com/diego/seo-htacces/nombre-valor/valor1/1/valor2/2
mediante el print_r conocemos lo valores como no lo has mostrado quedando lo siguiente como resultado.
Array
(
[valor1] => 1
[valor2] => 2
)
Pero qué debo hacer para ocupar eso valores, por ejemplo en una suma ?? ó imprimir cada uno con un simple echo
May 29, 2010 a las 1:04 am
Hola buen post, yo hice uno similar pero con regExp inspirado en WP_rewrite-api la de WordPress http://www.calinsoft.com/2008/08/urls-amigables-basado-en-wp_rewrite-api.html saludos.
September 7, 2010 a las 8:31 pm
Hola buen post, esto era lo que estava buscando…hace dias, leí tu otro post del MVC y no dude en realizarlo e implementarle las url amigables de este ultimo…
pero tengo problemas con los estilos CSS…
al principio todo anda bien url: localhost/controlador y todo carga bien, se ven imágenes y CSS pero cuando coloco “/” ej.: http://localhost/controlador/ ó http://localhost/controlador/accion ya no reconocen los CSS ni las imágenes aunque la lógica de las clases funciona perfectamente ya ha pasado algunos años desde la publicación del post así que si alguien tiene una salida lo agradecería…
Felicidades por el post gracias
September 15, 2010 a las 7:04 pm
Hola, en primer lugar decir que no se nada de programación. Estoy intentando hacer url amigables pero me vuelvo loco con los signos que aparecen y no consigo que funcione.
Tengo esta url condado.php?=Cill-Dara&id=12
dentro de una subcarpeta por ejemplo pais
es decir misitio.com/pais/condado.php?=Cill&id=12
Quisera tener como url amigable
misitio.com/pais/condado-Cill.html o también sin el html serviria.
¿que lineas tendría que poner en el .htacess para que funcione poniendo el htacess en la misma subcarpeta? osea, las lineas tal cual con todos los signos y códig para solo copiar y subir el htacess.
¿me vale con subir el htacess a la subcarpeta pais?
el tema es que no quiero que afecte a otras carpetas o paises.
Gracias
April 8, 2011 a las 12:19 pm
hola buen aporte
tengo un problema, tu codigo me ha funcionado bien, pero como puedo lograr limpiar la URL, lo que me pasa es lo siguiente cuando entro a mi sitio la primera ves toma por default la ruta:
http://localhost/misitio/Index/index
pero las siguientes ocaciones me reescribe en la URL:
localhost/misitio/Index/Index/index
y asi sucecivamente las nuevas llamadas se la va anexando a lo que la URL ya tenia hasta llegar a un :
localhost/misitio/Index/Index/Index/Index/Index/Index/Index/Index/index
o con cualquiera de los parametros que utilice
como le puedo hacer?? para evitar esto