URLs limpias con htaccess en PHP

Resumen

¿Cansado de URLs sucias con signos de interrogación y parámetros visibles? El archivo .htaccess es la pieza que te falta para transformar domain.com/?page=services en algo limpio como domain.com/services, ideal para SEO y para usuarios que quieren leer una dirección sin tropezar.

Esta guía está pensada para quienes ya trabajan con un front controller en PHP y quieren dar el siguiente paso: servir URLs amigables, optimizadas para search engine optimization, sin romper la lógica que ya tienen funcionando.

¿Qué es el archivo htaccess y para qué sirve en PHP?

El .htaccess es un archivo de configuración de Apache que actúa como traductor entre lo que el usuario escribe en la barra de direcciones y lo que tu front controller puede entender [02:00].

La lógica es simple: el usuario escribe domain.com/contacto, el .htaccess intercepta esa petición y la reescribe internamente como domain.com/index.php?page=contacto. El resultado es una URL limpia por fuera y un comportamiento idéntico por dentro.

¿Qué hace el archivo .htaccess? Reescribe URLs entrantes según reglas que tú defines. Sirve para limpiar direcciones, redirigir páginas y proteger rutas, todo sin tocar el código PHP de tu aplicación.

¿Por qué usar un virtual host antes de configurar htaccess?

El .htaccess funciona mejor cuando vive directamente en la raíz del dominio, no dentro de subcarpetas tipo localhost/php-intermedio/htaccess. Por eso conviene crear un virtual host como michilango.test que apunte a la carpeta del proyecto y se redirija a 127.0.0.1 en el archivo de hosts.

Con el virtual host listo, copias los archivos del front controller anterior y ya tienes el terreno preparado para agregar reglas de reescritura.

¿Cómo habilitar mod_rewrite en Apache según tu sistema operativo?

Antes de escribir una sola regla, necesitas tener activo el módulo mod_rewrite en Apache. Sin él, tu archivo .htaccess será ignorado por completo.

La ubicación del archivo de configuración cambia según el entorno:

  • En macOS con chip M1 (Homebrew), edita /opt/homebrew/etc/httpd/httpd.conf [10:30].
  • En macOS con Intel, busca /usr/local/etc/httpd/httpd.conf.
  • En Linux, abre /etc/apache2/apache2.conf.
  • En XAMPP suele venir habilitado por defecto.

En los tres casos hay que descomentar la línea LoadModule rewrite_module modules/mod_rewrite.so y reiniciar Apache con apachectl -k restart.

¿Cómo activo mod_rewrite en Linux? Además de descomentar la línea en apache2.conf, ejecuta el comando a2enmod rewrite y reinicia Apache. Sin ese comando, el módulo no queda activo en distribuciones basadas en Debian o Ubuntu.

¿Cómo escribir reglas de reescritura para URLs amigables?

Dentro de la carpeta raíz del proyecto creas un archivo llamado exactamente .htaccess (con el punto inicial). El contenido base que cubre la mayoría de los casos es este:

apache RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)$ index.php?page=$1 [QSA,L]

Cada línea cumple una función concreta y vale la pena entenderla pieza por pieza.

¿Qué hacen RewriteCond y RewriteRule?

RewriteEngine On activa el motor de reescritura para esa carpeta. Sin esta línea, el resto se ignora.

Las dos RewriteCond son condiciones de seguridad. La primera dice: si lo que el usuario escribió corresponde a un archivo real (!-f significa no es archivo, así que la condición se cumple cuando NO existe), entonces sí aplica la regla. La segunda hace lo mismo con directorios (!-d).

Esto evita que el .htaccess intercepte peticiones a archivos legítimos. Si tienes una carpeta llamada pages y escribes michilango.test/pages, Apache servirá su índice sin redirigir nada [07:15]. Pero si escribes services y esa carpeta no existe, la regla sí se dispara.

¿Qué significa la expresión regular en RewriteRule?

La parte ^(.*)$ es una expresión regular que captura cualquier texto que el usuario escriba después del dominio:

  • El símbolo ^ marca el inicio de la cadena.
  • El símbolo $ marca el final.
  • El punto . representa cualquier carácter.
  • El asterisco * indica que ese carácter puede repetirse cero o más veces.
  • Los paréntesis () agrupan lo capturado en una variable llamada $1.

Entonces, cuando alguien visita michilango.test/services, la regla traduce internamente a index.php?page=services. Si visita michilango.test/queso, llega como index.php?page=queso. El front controller recibe el parámetro page por GET tal como lo hacía antes, sin cambiar una sola línea de PHP.

¿Para qué sirve $1 en htaccess? Es la variable que guarda lo capturado entre paréntesis en la expresión regular. Te permite reutilizar lo que el usuario escribió y pasarlo como parámetro al script PHP que recibe la petición.

¿Cómo se comporta el front controller con URLs limpias?

Una vez configurado el .htaccess, tu index.php sigue leyendo $_GET['page'] igual que antes. La diferencia es que ahora ese parámetro llega desde una URL limpia.

Si escribes michilango.test/services, carga la vista de servicios. Si escribes michilango.test/contact, carga contacto. Si no escribes nada, carga home por defecto. Y si escribes algo que no existe como ruta válida, también cae en home porque el front controller gestiona ese caso.

Este patrón es exactamente el que usan frameworks como Laravel, que traen un .htaccess preconfigurado para que no tengas que pelearte con expresiones regulares en proyectos profesionales. Aun así, entender qué pasa por debajo te da control real sobre el enrutamiento de tus aplicaciones.

¿Ya probaste tus propias reglas de reescritura? Cuéntame en los comentarios qué tipo de URLs estás generando y si encontraste algún caso donde la regla básica se quedó corta.

      URLs limpias con htaccess en PHP