Cómo crear URL amigables paso a paso

por

Una parte fundamental e imprescindible de las técnicas SEO es la de generar URLs amigables. Estas nos permiten recordar más fácilmente una URL y, además, permiten a los spiders de google posicionarte mejor.

¿Que es una URL amigable?

Una URL amigable es aquella que detalla de forma precisa el contenido de la página y es perfectamente entendible para los ojos de un usuario inexperto. Pongamos un ejemplo:

Esto NO es una url amigable: www.tudominio.es/cargarNoticia.php?id=12

Esto SI es una URL amigable: www.tudominio.es/esta-es-una-noticia-de-prueba

Como podéis ver la diferencia es notable. Mientras que en la primera simplemente vemos cómo se llama a una página "cargarNoticias.php" y se le pasa un "id", en la segunda vemos como en la propia URL añadimos el título de la noticia "esto-es-una-noticia-de-prueba"

Como habréis intuido ya, es mucho mejor una URL del segundo tipo que del primero y google asi lo entiende.

Además es uno de los factores que más valora google a la hora de posicionar una página.

¿Cómo podemos generar URL amigables?

Para generar este tipo de URL amigables tenemos que hacerlo a través de un fichero llamado ".htaccess" que, mediante una serie de reglas y expresiones regulares, nos permite configurar los redireccionamiento o enmascaraciones de URLs adecuados.

Configurando mi servidor

Para que el fichero .htaccess funcione correctamente debemos asegurarnos que nuestro servidor APACHE tenga habilitado el modo de reescritura de URL. Para ello haremos lo siguiente:

1º Debemos tener activo el módulo mod_rewrite de apache. En el fichero "httpd.conf" deberíamos tener algo como esto: LoadModule rewrite_module modules/mod_rewrite.so . Aseguraros de que no esté comentado con #. Por lo general viene habilitado.

2º Debemos permitir la reescritura de URLs en el servidor. Para ello, en el mismo fichero "httpd.conf" deberíais tener algo como lo siguiente:

<Directory />

    Options FollowSymLinks

    AllowOverride All

    Order deny,allow

    Allow from all

    Satisfy all

</Directory>

Esta estructura suele venir aunque a veces viene con algunas líneas a "deny". Cambiadlas y ponedlas a "allow".

3º Por último debéis crear el fichero .htaccess en la raiz de vuestro proyecto. Fijaros que es un fichero sin extensión.

Con estas 3 simples pasos tendríais habilitadas las URL amigables y , ya, solo os quedaría generar las reglas de reescritura que vosotros queráis.

Ejemplos de .htaccess

A continuación, vamos a ver unos ejemplos simples pero que sin duda serán de los que más utilicéis ya que las URL amigables suelen ser siempre muy parecidas.

Dentro de vuestro fichero .htaccess debéis escribir lo siguiente:

Vamos a hacer que al escribir noticia/esto-es-una-noticia-de-prueba_13 nos mande a cargarNoticia.php?id=13 y se vea como noticia/esto-es-una-noticia-de-prueba_13

	RewriteEngine On

	RewriteRule ^noticia/(.+)_([0-9]+)$ cargarNoticia.php?id=$2

Vamos a hacer que al escribir noticia/esto-es-una-noticia-de-prueba te mande a cargarNoticia.php?id=esto-es-una-noticia-de-prueba y se ve producto/esto-es-una-noticia-de-prueba

	RewriteEngine On

	RewriteRule ^noticia/(.+)$ cargarNoticia.php?id=$1

Vamos a hacer que al escribir home.html te mande hola.html y se vea home.html

	RewriteEngine On

	RewriteRule ^home.html hola.html

Vamos a hacer que al escribir home.html te mande a http://www.google.com y se vea http://www.google.com

	RewriteEngine On

	redirectMatch 301 /home.html http://www.google.com

Vamos forzar a que tu dominio empiece por www, por ejemplo, si pones http://tudominio.com te redirecciona a http://www.tudominio.com

	RewriteCond %{HTTP_HOST} ^tudominio.com [NC]

	RewriteRule ^(.*)$ http://www.tudominio.com/$1 [L,R=301]

Espero que os sea de utilidad y, ya sabéis, las URLs amigables haran que vuestra web salga más arriba en los buscadores.

COMENTARIOS

30-01-2014 16:06:47
Hola ando buscando alguien que me de ascesoria por skype y podemos llegar a un acuerdo economico, mis dudas son sobre htacces y regexp no se si te interese, en el skype me encuentras como mikemoralesdj
28-11-2013 18:34:39
Tienes toda la razón, el problema es que este blog tiene ya mucho tiempo y el posicionamiento en los buscadores esta con las URL no amigables y si las cambiase perdería todo ese posicionamiento favorable. Ojala pudiera cambiarlo pero es peor el remedio que la enfermedad en este caso ;)
28-11-2013 03:44:40
y si lo aplicas a tu pagina xD , en casa de herroro cuchillo de palo ajajaj
08-11-2013 14:30:40
Hola Jose, en tu caso creo que tal y como lo tienes a día de hoy implementado no te convendría cambiar a URL amigables ya que las URL que tienes indexadas por Google son las que me has puesto y si las cambias tendrás que empezar de cero en Google en ese aspecto. Si aun asi lo quieres hacer lo primero que deberías hacer es cambiar todas las URLs del portal a las nuevas. Por ejemplo: http://www.una_web.com/nube_articulos.php?pg=0&newlang=es las cambiaría por http://www.una_web.com/es/nube_articulos?pg=0 Para hacer esto deberias crear en el htaccess una entrada similar a esta: RewriteEngine On RewriteRule ^/([a-z]+)/nube_articulos nube_articulos.php?newlang=$1 [L,QSA] Es un código hecho sobre la marcha y a lo mejor no funciona pero es para que veas un poco la idea. Una vez hayas cambiado todas las URLs y hayas creado las reglas en el htaccess correspondientes deberías redireccionar mediante redirecciones 301 todas las URLs antiguas a las nuevas. Viendo un poco tus páginas, si vas a hacer esto creo que te vendría bien un lavado completo de cara del portal y pasarte a algun CMS como Drupal que te gestiona este tipo de URLs de forma automática. Mi recomendación es que si estas dispuesto a cambiar las URLs sería mejor que aprobeches para actualizarte y pasarte a algun CMS como Drupal, a la larga te compensará y te hara la vida más sencilla a la hora de publicar y gestionar contenidos.
08-11-2013 13:17:47
Hola Sergio: Ten una web que actualmente genera las url de esta forma, y no tengo idea de htaccess. ¿Como puede hacer las url amigables? ¿tengo que reescribir el codigo para formarlas? ¿las Urls que estan en google (buscadores) como las redirecciono a las nuevas? NUBE de articulos http://www.una_web.com/nube_articulos.php http://www.una_web.com/nube_articulos.php?pg=0&newlang=es http://www.una_web.com/nube_articulos.php?pg=0&newlang=pt CONSULTA del catalogo http://www.una_web.com/catalogo.php?inicial=A&pg=3&newlang=es http://www.una_web.com/catalogo.php?inicial=A&pg=3&newlang=pt CONSULTA articulos // si viene desde la pagina prinicipal http://www.una_web.com/articulos.php?nart=Añil&nregart=1105&pg=n // si viene desde la pagina de NUBE de articulos http://www.una_web.com/articulos.php?nart=Añil&nregart=1105&pg=0 // si viene desde la CONSULTA del catalogo http://www.una_web.com/articulos.php?nart=Añil&nregart=1105&pg=3&newlang=es http://www.una_web.com/articulos.php?nart=Añil&nregart=1105&pg=3&newlang=pt
31-10-2013 03:59:59
Nice blog )
04-09-2013 22:38:20
En principio no creo que hubiera problema aunque dependerá de la velocidad de tu hosting y de tu BBDD. Sólo puedo decirte que trates de reducir lo máximo posible las consultas a la BBDD y si puedes recuperar los productos de las categorías en una sola consulta mejor que 1 por categoría ya que reducirás los accesos a la base de datos.
03-09-2013 00:43:51
gracias @Sergio González Barrios por las respuestas de verdad lo he pensado con la paginacion pero no seria seguro y en caso de esto es la mejor manera asi lo hago otra cosa si por ejemplo quiero saber cuantos productos hay en cada categoria / fabricante hay que hacer una consulta en la db con un bucle para cada cadegoria (tengo 15 categorias y para cada categoira hay que buscar en la lista de productos para sacar cuantos productos tiene esa categoira)(lo uso casi siempre para estas cosa ; el ej ha sido exagerado 100/200/300) mi pregunta es si el bucle serepite de 10 / 20(como maximo) veces hay algun problema (por ejemplo si tengo al mismo tiempo 20 clientes en esa pagina)(el script para saber cuantos productos hay en cada categoria lo tengo casi en todas las paginas)?? Qué me recomendas cambiar para no tener problemas ?? ¡¡¡¡¡¡¡¡*** Gracias por las respuestas me han sido de gran ayuda ***¡¡¡¡¡¡
02-09-2013 22:29:25
La verdad es que me parece un número bastante alto de productos para mostrar a la vez. En el caso de que fuese un listado te recomendaría que los paginases y asi limitarías los resultados a unos 10-20 por página. Además de que los podrías obtener con una sóla consulta filtrándolo por fabricante por ejemplo. En ningún caso deberías tener un bucle de 300 ni de 50, si ocurre esto pagina siempre para mejorar el rendimiento.
01-09-2013 13:37:20
el servidor no se satura con los datos de ese foreach (el foreache del carro de compra )pero cundo uso otro bucle para monstrar productos de un fabricante/categoria/etc(algo que primero tengo que buscar en db)(o si tengo 2 tablas en una la configuracion que tiene mas de 1 campo y hay que sacar todos los valores de la tabla y despues buscar de nuevo en db para cada valor ) que son con aproximacion 100 o mas si que se satura, lo que creo es que pasa eso porque hasta ahora he usado un servidor gratuito para pruebas pero ya me compre uno de pago por un año ; lo que quiero decir es: si hay algun fabricante/categoria/etc que tiene 100 /200 / 300 productos esto me puede saturar el nuevo servidor?? que otra opcion tengo para evitar eso ???
01-09-2013 11:46:29
No se muy bien porqué tu servidor se satura la verdad ya que tu foreach es un simple bucle de complejidad N. Deberías comprobar cuantas iteraciones realiza tu blucle no vaya a ser que esté haciendo muchas más de las que crees y por eso se satura.Haz un echo "hola"; justo antes del $result a ver cuantas veces se ejecuta. Por otro lado, en cuanto a la redirección que me comentas creo que la opción de la redirección 301 sería la mejor solución ya que evitas que pueda darse el caso de contenido duplicado.En tu caso sería algo como esto: redirectMatch 301 midominio.com/informacion/ midominio.com/informacion Con esto para los buscadores y los usuarios sólo existiría la URL midominio.com/informacion
31-08-2013 21:20:58
gracias @Sergio González Barrios lo que he hecho exactamente es: un array con un ref por cada producto en lo que gurada la informacion; despes guarda la info en $_SESSION['carro'] (functiona perfectamente); otra cosa si se hace una consulta dentro de un foreach esto satura el servidor //*** Que otra opcion tengo para hacer eso ***/ ej: foreach($_SESSION['carro'] as $k => $v){ $result = mysql_query("SELECT * FROM tblproducto where id = $v['idProducto']"); $row = mysql_fetch_array($result) echo $row['nombre']; echo $row['precio']; echo $row['imagen']; } ultima pregunta que no tengo clara: el url amigable es: "midominio.com/informacion" todo va bien pero si escribo: "midominio.com/informacion/" no muestra nada mi pregunta es si es recomandable hacer una redirection 301 o 302 de midominio.com/informacion a midominio.com/informacion/ ;
26-08-2013 17:27:54
Desde mi punto de vista, lo más sencillo para tu carro de la compra sería crear dos clases PHP "objeto" y "carrito". "objeto" sería la clase que define los pámetros de un objeto: color, tamaño, peso, precio, etc "carrito" sería simplemente un array de objetos en el que debería definir métodos como añadir, eliminar, precioTotal, etc. Las creas con los parámetros que necesites, les implementas los métodos que creas oportunos y luego una vez creas la sesión creas una variable de sesión que sea "carrito" y a ese carrito le vas añadiendo "objetos" con sus métodos previamente declarados. Espero que te ayude.
23-08-2013 23:55:15
gracias por las respuesta ya he resuelto mis porblemas con los url amigables de doy las gracias por compartir esta informacion tengo otra problema (no es sobre url amigable es sobre carro de compra) el carro de compra esta hecho en dos partes una con sessiones php y otra con base de datos (si un usuario se conecta a su cuenta se guarda en su carro personal ) mi problema es que no se como añadir al carro (con sessiones php ) modelos y colores de un producto mi codigo es lo siguiente : (eso es el codigo con lo cual se crea las sesiones ) switch ($action) { case 'sum': if(isset($_SESSION['carro'][$id])) $_SESSION['carro'][$id]=$valor; else $_SESSION['carro'][$id]=1; break; case 'add': if(isset($_SESSION['carro'][$id])){ $_SESSION['carro'][$id]++; $modelo ="cacao"; $_SESSION['$modelo'][$id] ; }else{ $_SESSION['carro'][$id]=1; } break; case 'remove': if(isset($_SESSION['carro'][$id])) { $_SESSION['carro'][$id]--; if($_SESSION['carro'][$id]==0){ unset($_SESSION['carro'][$id]); } } break; case 'removeProd': if(isset($_SESSION['carro'][$id])) { unset($_SESSION['carro'][$id]); }break; (codigo para monstrar los valores de la sesion) foreach($_SESSION['carro'] as $key=>$valor){ echo $key; echo $valor; /* hay muchisimo codigo no lo voy a escribir porque es muy largo*/ } lo que quiero hacer exactamente es "añadir"(si es posible) dos variables en esa Sesion o hacer algo parecido para que cuando hago el foreach me sale para cada producto el id ; la cantidad ; el modelo ; el color ;
18-08-2013 00:25:23
Muy buen articulo, lo necesitaba para realizar mi sistema sin problemas muchas gracias Sergio, visiten mi página http://thervn.blogspot.com
14-08-2013 20:44:58
A primera vista parece bastante completo. Creo que te falta el AND por sustituir. Por lo demás parece bastante robusto.
12-08-2013 23:08:26
gracias otra ves por responder encontre una funccion para limpiar lo que se envia por $_GET ( se que la mejor manera es usar un campo id(numerico) pero quiero algo como en los demas paginas (dominio.com/nombre-producto.html) me pueden decir si con esa funccion es suficiente para evitar el mysql injection function limpiarCadena($valor) { $valor = str_ireplace("SELECT","",$valor); $valor = str_ireplace("COPY","",$valor); $valor = str_ireplace("DELETE","",$valor); $valor = str_ireplace("DROP","",$valor); $valor = str_ireplace("DUMP","",$valor); $valor = str_ireplace(" OR ","",$valor); $valor = str_ireplace("%","",$valor); $valor = str_ireplace("LIKE","",$valor); $valor = str_ireplace("--","",$valor); $valor = str_ireplace("^","",$valor); $valor = str_ireplace("[","",$valor); $valor = str_ireplace("]","",$valor); $valor = str_ireplace("\\","",$valor); $valor = str_ireplace("!","",$valor); $valor = str_ireplace("¡","",$valor); $valor = str_ireplace("?","",$valor); $valor = str_ireplace("=","",$valor); $valor = str_ireplace("&","",$valor); return $valor; }
12-08-2013 17:59:15
Probablemente esas páginas utilicen algún filtro mediante expresiones regulares para que no se introduzcan expresiones como la que has puesto: drop, insert,etc. Como te digo,hay cientos de combinaciones posibles y dependen de cada caso pero utilizando identificaciones numéricos te olvidas de todas y simplificas mucho a la vez que mejoras el rendimiento ya que una busqueda en BD de un valor numérico es mucho más rápida que la de un string.
12-08-2013 12:00:41
gracias por responder ; si uso una funcion para que elimine los caracteres extraños si un cliente inserta 'drop table productos' en el campo del producto esta funcion no vale de nada, como usted ha ducho @Sergio González Barrios la mejor opcion es por id (numerico) pero he visto paginas que no tiene id numerico esto significa que todas esas paginas tiene vulnerabilidades de MySQL injection ??? (no creo porque son paginas muy grandes)
11-08-2013 12:14:42
Hola Andrei, la inyección de SQL cambia para cada caso. En el tuyo, si el ID fuese siempre siempre un número entero lo tendríamos fácil ya que solamente tendrías que asegurarte de que no introducen ningún caracter que no sea un número. En caso de que el ID pueda llevar letras debes filtrarlo para que no lleve caracteres extraños como $ . ; etc Estos son los caracteres que te la pueden 'liar'. Lo más recomendable es hacer que el ID sea numérico y así nunca podrías tener problemas ya que sólo deberías filtrar si es un número o no y en caso de que no lo sea muestras la tiípica pantalla de error.
10-08-2013 17:18:44
gracias por responder a mi pregunta anterior; quiero preguntar algo mas: eso es mi codigo como puedo evitar la injection MySQL ; mi codigo : $varProducto_obtenetproducto = "0"; if (isset($_GET['id'])) { $varProducto_obtenetproducto = $_GET['id']; } mysql_select_db($database_conexion, $conexion); $query_obtenetproducto = "SELECT * FROM tblproducto WHERE tblproducto.strUrlamigable = '$varProducto_obtenetproducto'"; $obtenetproducto = mysql_query($query_obtenetproducto, $conexion) or die(mysql_error()); if(mysql_num_rows($obtenetproducto)>0) { $row_obtenetproducto = mysql_fetch_assoc($obtenetproducto); $totalRows_obtenetproducto = mysql_num_rows($obtenetproducto); }else{ $error = 10; $row_caut = 0; } le paso el nombre del producto por $_GET ej: http://dominio.com/productos.php?id=nombre-producto como se puede ver si se cambie el nombre del producto por algun codigo myslq se puede borrar o distruir la db
13-07-2013 01:07:35
Hola @andrei, mientras el id que uses sea único y el contenido también lo sea no tendrás problema.

Debes asegurarte de que google sólo pueda rastrear tu url dominio/hoy.html y eso lo consigues si sólo usas la URL para añadir links internos.

Si tienes alguna duda más pregunta sin problema :)
12-07-2013 19:00:30
mi pregunta es si tengo una pagina dominio/noticia.php?id=hoy y el url amigable dominio/hoy.html voy a tener problemas con contenido duplicado????
01-07-2013 03:55:54
Excelente, por mucho tiempo estuve buscando una explicación "Amigable" acerca de este tema, puesto que en la web solo hay mega-tutoriales acerca de htacces. Excelente blog, Saludos y gracias por compartir
16-06-2013 11:27:58
Me legro que lo solucionaras freddy. Podrías publicar la función para que futuros usuarios puedan tenerlo disponible? Además actualizaré el post y añadiré la regla nueva. Gracias!
15-06-2013 17:26:04
Hola Sergio Te cuento que lo arregle para lograr esto localhost/descripcion/1/Esta-es-mi-primera-noticia con la funcion urls_amigables();
15-06-2013 00:21:05
Sergio ya lo solucione mi regla es está: RewriteRule ^descripcion/(.+)$ descripcion.php?id_noticia=$1 en el php es : <a href="descripcion/<?php echo $id_noticia; ?>/>noticia x</a> bueno el resultado fue /descripcion/2/ luego ya ahora le agregue una nueva variable para ver el titulo de la noticia <a href="descripcion/<?php echo $id_noticia; ?>/<?php echo $titulo; ?>" >noticia x</a> El resultado es: /descripcion/2/Esta%20es%20mi%20Segunda%20noticia Pero el problema es de que quiero que se vea con guiones así por ejemplo xd localhost/descripcion/1/Esta-es-mi-primera-noticia . gracias man por responder.
13-06-2013 22:24:53
Hola @freddt, puedes explicarme más cúal es tu problema y qué quieres hacer exactamente? Tal y como lo planteas tanto el punto 1 como el 2 te servirían para crearte Friendly URLs de tus noticias.
13-06-2013 06:20:09
tengo un sistema de noticias que envia un id por get mi pagina es un index.php y abajo estan las noticias al pinchar en una de ellas me envía a descripcion.php?id_noticia=6 no puedo crear las reglas bien para el htaccess gracias de antemano su alguien sabe..

DEJA TU COMENTARIO