Cómo crear permalinks agradables
La idea de este artículo es mostrar un sencillo ejemplo de cómo hacer que los links de nuestras aplicaciones web sean “bonitos”, algo así como los que podemos utilizar con WordPress. De tal manera no tendríamos links como estos:
http://www.sitio.com/index.php?accion=consultar&objetivo=personas
Sino algo estéticamente más agradable como:
http://www.sitio.com/personas/
¿Qué necesito?
Es necesario tener en cuenta los prerrequisitos para poder hacer esto. Para este ejemplo voy a suponer que la aplicación la estás haciendo sobre el servidor Apache, y que estás programando en PHP+MySQL. Necesitas:
- Manejar la mayor parte del trabajo con el archivo index.php. Esto más que un requisito es un consejo. Cuando estés desarrollando aplicaciones en PHP es recomendable que la mayor parte del sistema tenga que ser procesado inicialmente por este archivo, el cual se encargará de manejar todas las peticiones y utilizar los módulos que se necesiten. Esto, por supuesto, NO quiere decir que TODO el código vaya dentro del archivo index.php; una buena práctica es separar el código en módulos y llamarlos con funciones como include o require.
- Es necesario tener instalado el mod_rewrite, el cual se utilizará desde un archivo .htaccess. El ModRewrite es un módulo para Apache que por lo general se configura (definir reglas) en el archivo httpd.conf, pero es posible poner una configuración ModRewrite en cualquier directorio de nuestro servidor web dentro del archivo .htaccess.
- Puesto que de acuerdo al string que pasemos en la URL se debe determinar qué hacer, es necesario hacer algo de esto:
- Hacer que dentro de la base de datos la llave primaria de la tabla a consultar sea una cadena de texto, ó
- Hacer otro campo en la tabla de MySQL aparte de la llave primaria
Ejemplo
Para nuestro ejemplo necesitamos un servidor Apache con ModRewrite, PHP y MySQL. Lo primero es crear la base de datos, así:
create database ejemplo; create table contenidos( id int(5) primary key auto_increment, titulo varchar(50), contenido varchar(1000), slug varchar(50));
Luego creamos una carpeta dentro del htdocs de apache, en donde pondremos los archivos de nuestro ejempo (mkdir /opt/lampp/htdocs/ejemplo). Hecho esto, lo siguiente es crear el archivo .htaccess, en el cual indicaremos las reglas del ModRewrite. En nuestro ejemplo tenemos algo como esto:
# Esto es un comentario
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /ejemplo/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /ejemplo/index.php [L]
</IfModule>
Una explicación breve de este .htaccess:
- En los archivos .htaccess es posible hacer comentarios anteponiendo el simbolo numeral (almohadilla como dicen en España)
- <IfModule mod_rewrite.c>: Esta instrucción funciona como un if, que verifica si el ModRewrite está instalado.
- RewriteEngine On, activa el ModRewrite.
- RewriteBase /ejemplo/, asigna el directorio base donde trabajará el ModRewrite
- RewriteCond %{REQUEST_FILENAME} !-f y RewriteCond %{REQUEST_FILENAME} !-d, la instrucción RewriteCond funciona como una condición que en caso de ser verdadera hará que se ejecute una regla (RewriteRule) del ModRewrite. Funciona con expresiones regulares. En este caso lo que estamos verificando es si la petición se trata de un archivo (-f) o directorio (-d) que no (!) existe, en cuyo caso ejecuta la RewriteRule de abajo. Pero ¿para qué esto? Dado que las peticiones que hacemos usando URL bonitas no existen físicamente en el servidor, podemos aprovecharlas para indicar que dichas URL las manejará el archivo index.php, es decir, si por ejemplo hacemos una consulta como:
http://www.sitio.com/link-agradable
y en dicho servidor no existe ninguna carpeta o archivo que tenga el nombre link-agradable, el control de dicha petición se enviará al archivo index.php.
- RewriteRule . /ejemplo/index.php [L], ejecuta la regla que en este caso hace que el control de la aplicacion pase al archivo index.php, el cual se encargará de analizar la URL y realizar las operaciones adecuadas. La instrucción [L] hace que cualquier otra regla por debajo de esa linea no se cumpla.
- </IfModule>, cerramos nuestro if.
Vamos ahora con nuestro archivo index.php:
<?php
//URL base de la aplicacion
$base = "http://localhost/ejemplo/";
//Crear la conexion a la base de datos
$conexion = mysql_connect("localhost", "root", "");
mysql_select_db("ejemplo", $conexion);
//Si se requiere unicamente el index
if(("http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']) == $base ||
basename($_SERVER['REQUEST_URI']) == "index.php")
$contenido = "Lo que vaya en el index por defecto";
else {
$id = $_GET["id"];
//Si es una URL fea-asquerosa...
if(!empty($id))
$consulta = mysql_query("SELECT contenido FROM contenidos WHERE id = $id", $conexion);
//Si es una URL bonita...
else
{
//Obtener el nombre clave
$slug = basename($_SERVER['REQUEST_URI']);
$consulta = mysql_query("SELECT contenido FROM contenidos WHERE slug = '$slug'", $conexion);
}
//Si la consulta es correcta...
if(mysql_num_rows($consulta) > 0)
$contenido = mysql_result($consulta, 0, 0);
//Informar del terrible error
else
$contenido = "Lo que estás buscando no existe
";
}
?>
<html>
<head><title>Un ejemplo</title></head>
<body><?php echo $contenido ?></body>
</html>
- Línea 3: es recomendable para este tipo de aplicaciones (y para casi todas en general), que tengamos una URL fija definida para nuestra aplicación. En este caso almacenamos el string http://localhost/ejemplo/ en la variable $base.
- En las líneas 5 y 6 creamos la conexión a la base de datos.
- En el if de la línea 8 verificamos si la petición HTTP es para la raiz de nuestro proyecto (llamar simplement al index.php), de lo contrario…
- En las líneas 12 y 14 verificamos si se trata de una petición GET normal, en la que pasamos pares variable-valor dentro de la URL. En cuyo caso se realiza una consulta a la base de datos tomando en cuenta las variables GET (línea 15).
- Si la peticion está formada como una URL bonita, creamos una variable llamada $slug que contiene el nombre base de la URI (línea 20), es decir, si la peticion es http://www.sitio.com/link-agradable, el nombre base de la URI es link-agradable. Posteriormente, en la línea 21 hacemos una consulta en la base de datos buscando un registro que contenga dicho slug.
- En la línea 24 verificamos si la consulta ejecutada anteriormente contiene registros, en cuyo caso pone el contenido en la variable $contenido. Sino, se mete en esa variable un mensaje que dice que no se encontró el registro.
Hecho esto, nuestra aplicación tendrá el siguiente comportamiento:
La aplicación por defecto:

Una consulta a la antigua (URL fea):

Una consulta estéticamente más bonita:

Cuando no encuentra un registro:

Enlaces
- Descargar archivos del ejemplo click aquí
- Documentación ModRewrite
24 Comentarios | deja el tuyo





Gracias!, me ha servido mucho
Me alegra que te haya servido.
Un saludo
Excelente!!!!
Me está volviendo loca ésto, ya hice lo del .htacces, pero mi theme, tiene el index vacio O.O y lo más raro es que en localhost, funcionan a la perfección, pero en mi blog oficial no O.O O.O O.O
Hola, a mi me funciona perfecto todo, excepto por una cosa, cuando pongo el sitio http://localhost/mysite/about-us sale perfecto, pero si le agrego un slash / se pierden los estilos (http://localhost/prime/about-us/). Qué podrá ser?
k buen tutorial mis gracias, pero faltaria mas dinamismos es decir que se pueda mejorar con algunas funciones adicionales como son las variables se conviertan no carpetas si no es consecusion de la misma es decir ejemplo :
RewriteRule ^([A-Za-z0-9-]+)/?$ index.php?producto=$1 [L]
Pero si queremos definir una base para esa URL y que se vea así “ejemplo.com/productos/cama-colchon,html”,
miprograma.html?mivariable=$1
El MOD_REWRITE busca esta secuencia en cualquier dirección URL y mantiene el valor de la variable en $1, que es pegada en el string de salida (.*), es decir, (.*) se sustituye por el valor de la variable.
El resultado final es una sustitución de caracteres especiales, tales como ? por otros mas fáciles de interpretar por los buscadores (search engines), obteniendo direcciones estáticas y pasando el valor de las variable a la vez, muy útiles en el lenguaje PHP. La dirección URL sustituida será:
miprograma/cap/1.html
Hola Cristian! (creo que ese es tu nombre),
Es la primera vez que paso por acá y me alegra que el post que leí es uno que resuelve una duda que tenía desde hace mucho tiempo. No hay muchos tutoriales en español al respecto, por lo que te agradezco que te hayas tomado el tiempo para escribirlo! Mil gracias!
Leyendo el comentario de galax me surgió la duda sobre el código htaccess necesario para hacer que sea más dinámico el url. No soy muy ducho (aún) en htaccess, por lo que me tomé la molestia en consultarte a ver si estoy en lo correcto. El código que pongo a continuación será la adaptación de lo que tu propones con el código de galax, estaría bien así?:
# Esto es un comentario
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([A-Za-z0-9-]+)/?$ index.php?producto=$1 [L]
No estoy seguro, pero creo que esto (con algunos cambios en el script) permitiría asignar una categoría al principio del URL (tal cual lo hace WordPress) y luego el permalink del contenido. Voy bien? O estoy olvidando algo?
Saludos desde Venezuela!
Hola Héctor.
Muchas gracias por participar, es agradable ver que hay gente dispuesta a ayudar (sobre todo ahora que no cuento con tanto tiempo).
Respecto a tu comentario, me alegra que te haya servido, las gracias que me das me animan a seguir escribiendo.
Un saludo!
jeje que bueno hector deje este tema por me estoy concentrando en otras cosas pero apenas pueda lo retomamos y haremos cosas interezantes asi tipo wordpress como los permalink que maneja o un esilo mercado libre en fin si les intereza tengo el clon de facebook jeje y otras cositas esperemos que el buen amigo de cristhian complemente los argumentos de hector ya que este tema es sumamente importantisimo por si queremos generar trafico y link a las personas que sean legibles como lo estetico se nombra aqui, amigo cristhian comencemos a desarrollar la segunda version aqui con la colaboracion de todos y gracias por el post 10 puntos …
…..
Bueno Este es un ejemplo sencillo pero nos abrira los ojos, estube toda una tarde haciendo funcionar esto y nada pero cosas de la vida como le pasas a los programadores a menudo un dia llegue en la mañana y en 10 minutos saque este ejemplo sencillo y entendible bueno vamos a ver. primero que todo esto es un ejemplo usuando appserv en windows debes de buscar el archivo httpd.conf
y cambiar la linea
LoadModule rewrite_module modules/mod_rewrite.so
y quitarle el # al principio}
y debes de reiniciar el apache ….
bueno manos a la obra :
Digamos que tienes una tienda de ropa y que tus clientes pueden ver la ropa que tienes navegando por categoría y talla de la misma. Para esto tienes una aplicación que se llama de la siguiente manera:
tusitio.algo/mod/aplicacion_ropa.htm?tipo=playeras&sexo=femenino&talla=chica”"”"
No es para nada bonito el url, por lo que queremos que nuestros clientes puedan acceder de la siguiente manera:
http://localhost/playeras/femenino/chica.htm
creamos una carpeta que se llame mod en la www/mod/
y creamos el archivo index.php
espues creamos el archivo .htaccess
en windows ahi un inconveniente al creear este archivo por la razon que no tiene nombre al principio pero no importa si es posible crearlo bajandote el notepad ++ y le dices guardar como y te lo deja tal cual.
y en el escribimos lo siguiente :
RewriteEngine On
RewriteRule ^playeras/femenino/chica.htm index.php?tipo=playeras&sexo=femenino&talla=chica [L,NC]
y listo vamos y ejecutamos nuestro servidor local y damos la siguiente direccion:
http://localhost/mod/playeras/femenino/chica.htm
Como ves es más intuitivo y amigable.
Usando mod_rewrite no es necesario hacer ningún cambio en tu aplicación, ni siquiera es necesario que crees los directorios ‘playeras/’ ni ‘playeras/femenino’, tampoco es necesario que hagas un archivo que se llame chica.htm.
Lo que vamos a hacer es que cuando algún usuario haga un request de ‘http://localhost/playeras/femenino/chica.htm‘ usaremos el mod_rewrite para filtrar y convertir el url a ‘http://localhost/mod/aplicacion_ropa.php?tipo=playeras&sexo=femenino&talla=chica', pero todo esto detrás de las cortinas, usando la redirección interna como habíamos dicho.
Ya que estemos seguros que tenemos el mod_rewrite instalado y activo, vamos a crear un nuevo archivo de configuración htaccess
La conversión del url se hace por detrás por lo que el usuario no podrá ver nada de esto, sin embargo si verá el resultado que viene de la ejecución del url “real”.
Es importante comprender que mod_rewrite NO puede ser usado para cambiar el URL que el usuario ve es la barra de Dirección de su navegador a menos que una redirección externa es invocada. Sin embargo una dirección externa expone finalmente el url dinámico, así que mod_rewrite hace una redirección interna.
También es importante comprender que mod_rewrite cambia la dirección del archivo y las variables del url pedido pero NO cambia en ningún momento el despliegue de las mismas.
Archivos del ejemplo :
rapidshare/files/280444664/mod.zip
recuerden ponerle el com despues del rapidshare ya que al parecer no acepta comentarios con el punto co m o link por eso me toco dividir los comentarios disculpen las molestias..
ejemplo 1:
rapidshare.com/files/280444664/mod.zip
Herramienta Util para crear los mod_write
http://www.generateit.net/mod-rewrite/
espero k sea de su utilidad