Por qué organizar
Un proyecto que empieza con cuatro archivos sueltos y crece hasta veinte se vuelve difícil de tocar: cada archivo mezcla consultas a la base, reglas del negocio y HTML. Cambiar el color de un botón obliga a abrir un archivo que también inserta ventas, y un error en una línea rompe todo.
La solución no es «escribir más ordenado»: es separar responsabilidades. Cada parte hace una cosa y no conoce los detalles de las demás. Eso es lo que MVC propone.
MVC significa Modelo, Vista, Controlador: el modelo sabe de datos, la vista sabe de presentación y el controlador coordina.
Separar responsabilidades
| Parte | Qué hace | En la tienda |
|---|---|---|
| Modelo | Consulta y guarda datos; conoce la base y las reglas. | Producto, Venta: buscar, listar, insertar. |
| Vista | Muestra; no decide ni consulta. | El HTML del catálogo con los productos ya listos. |
| Controlador | Recibe la petición, pide datos al modelo y elige la vista. | «Mostrar el catálogo»: pide los productos y entrega la vista. |
La regla que hace la diferencia: la vista no consulta la base y el modelo no imprime HTML. Cuando se respeta, cambiar la presentación no toca la lógica, y al revés.
El ruteador
Todas las peticiones entran por un solo archivo —index.php— que mira la dirección pedida y decide qué controlador la atiende. Ese archivo se llama front controller o punto de entrada único.
$ruta = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
match ($ruta) {
'/', '/productos' => (new ProductoController())->listar(),
'/productos/crear' => (new ProductoController())->crear(),
'/ventas' => (new VentaController())->listar(),
default => http_response_code(404) . print('No encontrado'),
};
Con esto, agregar una página es agregar una línea al ruteador y el método en su controlador. Ya no hay un archivo suelto por pantalla, y todas las peticiones pasan por el mismo lugar: ahí se puede registrar, autenticar y aplicar cabeceras de seguridad una sola vez.
El punto de entrada
El index.php de la raíz hace tres cosas, en orden: cargar la configuración, armar el ruteador y despachar la petición.
<?php
declare(strict_types=1);
require __DIR__ . '/config/autoload.php';
require __DIR__ . '/config/conexion.php';
$ruta = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
// ... ruteador ...
Que todo entre por acá también simplifica la seguridad: si hay que exigir sesión en el área privada, se hace en el punto de entrada, no en cada archivo.
La estructura
tienda/
├── index.php ← punto de entrada único
├── config/
│ ├── conexion.php
│ └── autoload.php
├── src/
│ ├── Modelo/
│ │ ├── Producto.php
│ │ └── Venta.php
│ ├── Controlador/
│ │ ├── ProductoController.php
│ │ └── VentaController.php
│ └── Vista/
│ ├── productos.php
│ └── ventas.php
└── public/
├── css/
└── js/
La carpeta public/ es la única que debe quedar expuesta al servidor: ahí van CSS, JS e imágenes. El código PHP queda fuera de la carpeta pública, así una dirección mal escrita no puede pedir un archivo de código.
Resumen
- Separar responsabilidades evita el archivo que hace todo y no se puede tocar.
- Modelo = datos y reglas; Vista = presentación; Controlador = coordina.
- La vista no consulta la base; el modelo no imprime HTML.
- Un ruteador decide qué controlador atiende cada dirección.
- Un punto de entrada único centraliza configuración y seguridad.
- Solo
public/se expone; el código queda afuera.
En la próxima lección, lo que protege el sistema: permisos por rol, contraseñas, inyección SQL, XSS y CSRF.
Licencia. El material de esta página es elaboración propia de Prof Mauro Bobyk —a partir de las fuentes que detalla el pie del sitio— y se publica bajo una licencia Creative Commons BY-NC-SA 4.0.