Patrón MVC desde Cero
MVC (Model-View-Controller) separa tu aplicación en tres capas: el Modelo maneja los datos y la lógica de negocio, la Vista genera el HTML que ve el usuario, y el Controlador recibe las peticiones HTTP, coordina el Modelo y elige qué Vista mostrar. Esta separación permite que un diseñador trabaje en las vistas sin tocar la lógica, y un backend developer cambie la base de datos sin afectar la interfaz.
Construir un mini-framework MVC te enseña cómo funcionan Laravel, Symfony y CodeIgniter por dentro: un Router que mapea URLs a controladores, un Controller que procesa la petición y prepara datos, un Model que consulta la base de datos, y una View que renderiza el HTML con esos datos. Una vez entiendes este flujo, aprender cualquier framework PHP es cuestión de aprender su API, no sus conceptos.
<?php
// --- Router.php --- Mapea URLs a controladores
class Router {
private array $rutas = [];
public function get(string $path, array $handler): void {
$this->rutas["GET"][$path] = $handler;
}
public function post(string $path, array $handler): void {
$this->rutas["POST"][$path] = $handler;
}
public function resolver(): void {
$method = $_SERVER["REQUEST_METHOD"];
$path = parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH);
$handler = $this->rutas[$method][$path] ?? null;
if (!$handler) { http_response_code(404); echo "404"; return; }
[$clase, $metodo] = $handler;
(new $clase)->$metodo();
}
}
// --- Model.php --- Acceso a datos
class TareaModel {
private PDO $db;
public function __construct() {
$this->db = new PDO("sqlite:app.db");
}
public function todas(): array {
return $this->db->query("SELECT * FROM tareas")->fetchAll(PDO::FETCH_ASSOC);
}
public function crear(string $titulo): void {
$this->db->prepare("INSERT INTO tareas (titulo) VALUES (?)")
->execute([$titulo]);
}
}
// --- Controller.php --- Lógica de peticiones
class TareaController {
public function index(): void {
$model = new TareaModel();
$tareas = $model->todas();
include "views/tareas/index.php"; // Vista con $tareas
}
public function crear(): void {
$titulo = htmlspecialchars($_POST["titulo"] ?? "");
if ($titulo) (new TareaModel())->crear($titulo);
header("Location: /tareas");
}
}
// --- index.php --- Punto de entrada
$router = new Router();
$router->get("/tareas", [TareaController::class, "index"]);
$router->post("/tareas", [TareaController::class, "crear"]);
$router->resolver();
// --- views/tareas/index.php --- Vista HTML
// <h1>Tareas (<?= count($tareas) ?>)</h1>
// <?php foreach ($tareas as $t): ?>
// <p><?= htmlspecialchars($t["titulo"]) ?></p>
// <?php endforeach; ?>
Practica esta lección
Resuelve los ejercicios del curso de PHP en la app, gratis y con corrección automática.
Empezar a practicar