16: Limpiando la URL en PHP (MVC)
Introducción
Hola alumnos, en este tutorial vamos a aprender a limpiar las URLs en nuestra aplicación PHP bajo el patrón Modelo Vista Controlador (MVC). Vamos a solucionar un problema muy común y a hacer nuestra aplicación más profesional y segura.
¿Qué problema tenemos?
Ya hemos creado una página interactiva bajo el patrón modelo vista controlador, pero vamos a encontrar un pequeño problema. El usuario puede navegar entre los contenidos y son contenidos modulares.
El usuario no sabe que son contenidos modulares, solamente lo sabe la persona que desarrolló la aplicación. A través de los módulos tenemos:
Módulo de navegación
Módulo de contáctenos
Módulo de nosotros
Módulo de servicios
Estos módulos pueden tener su propia hoja de estilo, pero la idea no es esa. La idea es que primero hayamos hecho toda la plantilla completa y luego la separamos por módulos y esa misma hoja de estilo nos sirva para todos.
El error que aparece
Cuando el usuario inicia la aplicación en el index.php, PHP se va a encontrar con un error. ¿Por qué? Porque todos los enlaces los estamos llamando a través de una variable GET llamada action.
http://localhost/cursoPHP/03.MVC/index.php?action=serviciosPero para la página de inicio, la URL sería:
http://localhost/cursoPHP/03.MVC/index.phpEn este caso, la variable action no existe en la URL, por lo tanto el sistema no sabe qué módulo cargar y nos mostrará un error.
Solución paso a paso
Paso 1: Modificar el controlador para verificar si existe la variable GET
Vamos a editar el archivo controller.php. Necesitamos verificar si la variable action viene con información o no.
<?php
// controller.php
class EnlacesPaginasController {
public function enlacesPaginasController() {
// Verificamos si la variable action viene con información
if(isset($_GET["action"])) {
// Si trae información, guardamos ese valor
$enlacesController = $_GET["action"];
} else {
// Si NO trae información, asignamos "index"
$enlacesController = "index";
}
// Llamamos al modelo y le pasamos el valor
$respuesta = EnlacesPaginas::enlacesPaginasModel($enlacesController);
// Incluimos la vista correspondiente
include $respuesta;
}
}
?>Explicación del código:
isset($_GET["action"])- Esta función verifica si la variableactionexiste y tiene contenido.Si existe (
true), guardamos su valor en$enlacesController.Si no existe (
false), asignamos el valor "index" a$enlacesController.Luego enviamos este valor al modelo.
Paso 2: Modificar el modelo para manejar los enlaces
Ahora vamos a editar el archivo model.php para que reconozca el valor "index" y cargue la página de inicio.
<?php
// model.php
class EnlacesPaginas {
public function enlacesPaginasModel($enlacesModel) {
// Verificamos si el enlace está en nuestra lista blanca
if($enlacesModel == "nosotros" ||
$enlacesModel == "servicios" ||
$enlacesModel == "contactenos") {
$module = "views/modules/" . $enlacesModel . ".php";
} else if($enlacesModel == "index") {
// Si es index, cargamos la página de inicio
$module = "views/modules/inicio.php";
}
return $module;
}
}
?>Explicación del código:
Si
$enlacesModeles "nosotros", "servicios" o "contactenos", cargamos el módulo correspondiente.Si
$enlacesModeles "index", cargamos el módulo "inicio.php".Devolvemos la ruta del módulo a incluir.
Paso 3: Probar la solución
Actualizamos nuestra aplicación y hacemos clic en "Inicio". Veremos que:
La URL está limpia:
http://localhost/cursoPHP/03.MVC/index.phpLa página carga correctamente el módulo
inicio.php
¡Perfecto! Hemos solucionado el error.
Pero tenemos otro problema...
Ahora, ¿qué pasa si un usuario malintencionado que conoce PHP escribe en la URL?
http://localhost/cursoPHP/03.MVC/index.php?action=chicasComo "chicas" no está en nuestra lista de enlaces válidos, PHP mostrará un error. Esto no es seguro ni profesional.
Solución: Crear una lista blanca
Una lista blanca (whitelist) es un conjunto de valores permitidos. Todo lo que no esté en esta lista será rechazado o redirigido.
Vamos a modificar nuestro modelo para incluir una lista blanca:
<?php
// model.php - Versión mejorada con lista blanca
class EnlacesPaginas {
public function enlacesPaginasModel($enlacesModel) {
// LISTA BLANCA: solo estos valores son permitidos
if($enlacesModel == "nosotros" ||
$enlacesModel == "servicios" ||
$enlacesModel == "contactenos") {
$module = "views/modules/" . $enlacesModel . ".php";
} else if($enlacesModel == "index") {
$module = "views/modules/inicio.php";
} else {
// Si NO está en la lista blanca, cargamos inicio
$module = "views/modules/inicio.php";
}
return $module;
}
}
?>¿Qué hemos agregado?
Un
elsefinal que atrapa cualquier valor no permitido.Si el usuario escribe cualquier palabra que no esté en nuestra lista blanca, automáticamente lo redirigimos a la página de inicio.
Probando la lista blanca
Ahora, si un usuario escribe:
http://localhost/cursoPHP/03.MVC/index.php?action=chicasEn lugar de un error, verá la página de inicio. También funciona con:
http://localhost/cursoPHP/03.MVC/index.php?action=malicioushttp://localhost/cursoPHP/03.MVC/index.php?action=hackResumen de archivos finales
controller.php (Completo)
<?php
// controller.php
class EnlacesPaginasController {
public function enlacesPaginasController() {
// Verificamos si la variable GET existe
if(isset($_GET["action"])) {
$enlacesController = $_GET["action"];
} else {
$enlacesController = "index";
}
// Llamamos al modelo
$respuesta = EnlacesPaginas::enlacesPaginasModel($enlacesController);
// Incluimos la vista
include $respuesta;
}
}
?>model.php (Completo)
<?php
// model.php
class EnlacesPaginas {
public function enlacesPaginasModel($enlacesModel) {
// LISTA BLANCA - Solo estos enlaces son permitidos
if($enlacesModel == "nosotros" ||
$enlacesModel == "servicios" ||
$enlacesModel == "contactenos") {
$module = "views/modules/" . $enlacesModel . ".php";
} else if($enlacesModel == "index") {
$module = "views/modules/inicio.php";
} else {
// Cualquier otro valor no permitido va a inicio
$module = "views/modules/inicio.php";
}
return $module;
}
}
?>navegacion.php (Menú)
<!-- navegacion.php -->
<nav>
<ul>
<li><a href="index.php">Inicio</a></li>
<li><a href="index.php?action=nosotros">Nosotros</a></li>
<li><a href="index.php?action=servicios">Servicios</a></li>
<li><a href="index.php?action=contactenos">Contáctenos</a></li>
</ul>
</nav>Conclusión
Hemos aprendido a:
Limpiar la URL usando PHP para manejar cuando no existe la variable GET
Crear una lista blanca para evitar que usuarios malintencionados inyecten valores no deseados
Redirigir automáticamente los valores no permitidos a la página de inicio
Esto hace que nuestra aplicación sea:
Más profesional: URLs limpias y sin errores
Más segura: Evitamos inyección de parámetros no deseados
Más robusta: El sistema nunca muestra errores al usuario
En el próximo tutorial aprenderemos a optimizar aún más nuestro código y agregar nuevas funcionalidades.
URLs Amigables en PHP (URLs Limpias)
Introducción a URLs Amigables
Hola alumnos, en el tutorial anterior aprendimos a limpiar la URL solucionando el problema de la variable GET vacía y creando una lista blanca. Pero nuestras URLs todavía tienen ese formato con ?action= que no es muy bonito que digamos:
http://localhost/cursoPHP/03.MVC/index.php?action=nosotros
http://localhost/cursoPHP/03.MVC/index.php?action=servicios
http://localhost/cursoPHP/03.MVC/index.php?action=contactenos¿No sería mucho mejor si pudiéramos tener URLs como estas?
http://localhost/cursoPHP/03.MVC/nosotros
http://localhost/cursoPHP/03.MVC/servicios
http://localhost/cursoPHP/03.MVC/contactenos
http://localhost/cursoPHP/03.MVC/¡Eso se llaman URLs amigables (o friendly URLs)! Se ven más profesionales, son más fáciles de recordar y ayudan al posicionamiento en buscadores (SEO).
¿Cómo funcionan las URLs amigables?
Las URLs amigables funcionan mediante un archivo especial llamado .htaccess que reescribe las URLs. Este archivo le dice al servidor: "Cuando el usuario escriba una URL bonita, conviértela internamente a la URL con parámetros que nuestro sistema entiende".
Paso 1: Crear el archivo .htaccess
En la raíz de nuestro proyecto (carpeta 03.MVC), vamos a crear un archivo llamado .htaccess (con el punto al inicio):
# .htaccess
# Archivo para reescribir URLs y hacerlas amigables
# Activamos el motor de reescritura
RewriteEngine On
# Condición: No es un archivo real
RewriteCond %{REQUEST_FILENAME} !-f
# Condición: No es un directorio real
RewriteCond %{REQUEST_FILENAME} !-d
# Regla de reescritura
RewriteRule ^([a-zA-Z0-9_-]+)$ index.php?action=$1 [L]Explicación del código línea por línea:
RewriteEngine On- Activa el motor de reescritura de URLsRewriteCond %{REQUEST_FILENAME} !-f- Verifica que lo que pide el usuario NO sea un archivo realRewriteCond %{REQUEST_FILENAME} !-d- Verifica que lo que pide el usuario NO sea un directorio realRewriteRule ^([a-zA-Z0-9_-]+)$ index.php?action=$1 [L]- Toma cualquier palabra (letras, números, guiones) y la convierte enindex.php?action=palabra
¿Qué hace exactamente este archivo?
Imaginemos que el usuario escribe en el navegador:
http://localhost/cursoPHP/03.MVC/nosotrosEl archivo .htaccess intercepta esta petición y la transforma internamente en:
http://localhost/cursoPHP/03.MVC/index.php?action=nosotros¡Pero el usuario sigue viendo la URL bonita! Es como un "traductor" entre lo que ve el usuario y lo que entiende nuestro sistema.
Paso 2: Actualizar nuestro menú (navegacion.php)
Ahora que tenemos URLs amigables, podemos actualizar nuestro menú para usar estas nuevas URLs:
<!-- navegacion.php -->
<nav>
<ul>
<li><a href="/cursoPHP/03.MVC/">Inicio</a></li>
<li><a href="/cursoPHP/03.MVC/nosotros">Nosotros</a></li>
<li><a href="/cursoPHP/03.MVC/servicios">Servicios</a></li>
<li><a href="/cursoPHP/03.MVC/contactenos">Contáctenos</a></li>
</ul>
</nav>¿Ven la diferencia? Ya no usamos index.php?action=, sino directamente el nombre de la sección.
Paso 3: Verificar que nuestro controlador funcione
Lo bueno es que nuestro controlador y modelo ya están preparados para trabajar con estas URLs. Recordemos nuestro controller.php del tutorial anterior:
<?php
// controller.php
class EnlacesPaginasController {
public function enlacesPaginasController() {
// Verificamos si la variable action existe
if(isset($_GET["action"])) {
$enlacesController = $_GET["action"]; // Aquí llega "nosotros", "servicios", etc.
} else {
$enlacesController = "index"; // Si no hay action, va a index
}
// Llamamos al modelo
$respuesta = EnlacesPaginas::enlacesPaginasModel($enlacesController);
// Incluimos la vista
include $respuesta;
}
}
?>El sistema sigue funcionando igual, porque internamente http://localhost/cursoPHP/03.MVC/nosotros se convierte en index.php?action=nosotros, y nuestro controlador recibe "nosotros" como antes.
Paso 4: Actualizar el modelo para manejar mejor las URLs
Podemos mejorar nuestro modelo para que funcione perfectamente con las URLs amigables:
<?php
// model.php
class EnlacesPaginas {
public function enlacesPaginasModel($enlacesModel) {
// Lista blanca con todos los módulos permitidos
$modulosPermitidos = ["nosotros", "servicios", "contactenos", "inicio"];
// Verificamos si el enlacesModel está en la lista blanca
if(in_array($enlacesModel, $modulosPermitidos)) {
// Si es "inicio", cargamos inicio.php
if($enlacesModel == "inicio") {
$module = "views/modules/inicio.php";
} else {
// Para los demás, cargamos el módulo correspondiente
$module = "views/modules/" . $enlacesModel . ".php";
}
} else if($enlacesModel == "index") {
// Si viene "index", cargamos inicio
$module = "views/modules/inicio.php";
} else {
// Si no está en la lista blanca, cargamos inicio
$module = "views/modules/inicio.php";
}
return $module;
}
}
?>¿Qué mejoramos?
Usamos
in_array()para verificar si el valor está en la lista blancaHacemos el código más limpio y fácil de mantener
Si en el futuro agregamos más secciones, solo hay que agregarlas al array
$modulosPermitidos
Comparativa: Antes vs Después
Antes (URLs feas):
http://localhost/cursoPHP/03.MVC/index.php?action=nosotros
http://localhost/cursoPHP/03.MVC/index.php?action=servicios
http://localhost/cursoPHP/03.MVC/index.php?action=contactenos
http://localhost/cursoPHP/03.MVC/index.phpDespués (URLs amigables):
http://localhost/cursoPHP/03.MVC/nosotros
http://localhost/cursoPHP/03.MVC/servicios
http://localhost/cursoPHP/03.MVC/contactenos
http://localhost/cursoPHP/03.MVC/Estructura final de nuestro proyecto
03.MVC/
├── .htaccess # Archivo para URLs amigables
├── index.php # Punto de entrada
├── controller.php
├── model.php
├── controllers/
│ └── controller.php
├── models/
│ └── model.php
└── views/
├── modules/
│ ├── inicio.php
│ ├── nosotros.php
│ ├── servicios.php
│ ├── contactenos.php
│ └── navegacion.php
└── template.phpBeneficios de las URLs amigables
1. Profesionalismo
// Antes (parece sistema amateur)
$url = "index.php?action=nosotros";
// Después (parece sitio profesional)
$url = "/nosotros";2. SEO (Posicionamiento en buscadores)
Los buscadores como Google prefieren URLs limpias porque:
Son más fáciles de leer
Contienen palabras clave
Son más fáciles de recordar
3. Seguridad
Las URLs amigables ocultan que estamos usando parámetros GET, dificultando que usuarios malintencionados intenten inyectar código.
4. Facilidad de uso
<!-- Antes: URLs largas y feas -->
<a href="index.php?action=nosotros&lang=es&id=5">Nosotros</a>
<!-- Después: URLs limpias y bonitas -->
<a href="/nosotros">Nosotros</a>Posibles problemas y soluciones
Problema 1: El archivo .htaccess no funciona
Solución: Verificar que Apache tenga activado el módulo mod_rewrite. En XAMPP/WAMP normalmente viene activado.
Problema 2: URLs relativas vs absolutas
<!-- Esto puede fallar con URLs amigables -->
<a href="nosotros">Nosotros</a> <!-- MAL -->
<!-- Esto funciona siempre -->
<a href="/cursoPHP/03.MVC/nosotros">Nosotros</a> <!-- BIEN -->
<a href="<?php echo $base_url; ?>/nosotros">Nosotros</a> <!-- MEJOR -->Problema 3: Archivos CSS y JS que no cargan
Cuando usamos URLs amigables, las rutas relativas pueden confundirse. Solución: Usar siempre rutas absolutas desde la raíz.
<!-- En lugar de esto -->
<link rel="stylesheet" href="css/estilos.css">
<!-- Usar esto -->
<link rel="stylesheet" href="/cursoPHP/03.MVC/css/estilos.css">Ejemplo completo funcionando
Cuando un usuario hace clic en "Nosotros":
El navegador pide:
http://localhost/cursoPHP/03.MVC/nosotros.htaccess intercepta: "Esto no es un archivo real, lo convierto"
Transformación:
http://localhost/cursoPHP/03.MVC/index.php?action=nosotrosPHP procesa: Nuestro controlador recibe
action=nosotrosModelo verifica: "nosotros" está en lista blanca
Resultado: Se carga
views/modules/nosotros.php
¡Y el usuario nunca se entera de esta magia!
Conclusión
Las URLs amigables son el estándar en el desarrollo web moderno. Con un simple archivo .htaccess transformamos nuestras URLs feas en URLs profesionales, mejorando la experiencia del usuario, el SEO y la seguridad de nuestra aplicación.
En el próximo tutorial aprenderemos a crear un sistema de rutas más avanzado que nos permita tener URLs aún más complejas como:
/nosotros/historia/servicios/desarrollo-web/contactenos/mensajes/15
¡Practiquen estos conceptos y verán cómo sus aplicaciones se ven mucho más profesionales!
Comentarios
Publicar un comentario