Una buena arquitectura hace que tu código sea modular, mantenible, escalable y seguro. En esta guía aprenderás a implementar MVC en PHP desde cero, ideal para proyectos pequeños y medianos donde necesitas control total.
Principios de arquitectura de software
Una buena arquitectura hace que tu código sea:
- Modular: partes independientes que se pueden cambiar sin afectar al todo
- Mantenible: fácil de actualizar y corregir errores
- Escalable: listo para crecer con nuevas funciones
- Seguro: menos vulnerabilidades por código desorganizado
¿Qué es el patrón MVC?
MVC divide tu aplicación en tres capas claras que se comunican entre sí:
🗄️ Modelo
Maneja los datos y la lógica de negocio (acceso a base de datos)
🎮 Controlador
Recibe peticiones, procesa lógica y decide qué vista mostrar
👁️ Vista
Muestra la interfaz al usuario (HTML, CSS, presentación)
MVC no es un framework, es un patrón de diseño. Puedes implementarlo manualmente o usar frameworks como Laravel que ya lo incluyen.
Estructura de carpetas para MVC en PHP
Crea esta estructura en tu proyecto para mantener el código organizado:
├── /models
│ └── UserModel.php
├── /views
│ └── /users
│ └── index.php
└── /controllers
└── UserController.php
/config.php
/index.php
Implementación paso a paso
1️⃣ config.php: Conexión a la base de datos
<?php
// config.php
$servername = "localhost";
$username = "root";
$password = "";
$dbname = "mi_app";
$conn = new mysqli($servername, $username, $password, $dbname);
if ($conn->connect_error) {
error_log("Error de conexión: " . $conn->connect_error);
die("Error de conexión. Intenta más tarde.");
}
?>
2️⃣ Modelo (UserModel.php)
<?php
// app/models/UserModel.php
require_once '../config.php';
class UserModel {
private $conn;
public function __construct() {
global $conn;
$this->conn = $conn;
}
public function getAllUsers() {
$sql = "SELECT id, nombre, email FROM usuarios";
$result = $this->conn->query($sql);
return $result ? $result->fetch_all(MYSQLI_ASSOC) : [];
}
public function getUserById($id) {
$stmt = $this->conn->prepare("SELECT * FROM usuarios WHERE id = ?");
$stmt->bind_param("i", $id);
$stmt->execute();
return $stmt->get_result()->fetch_assoc();
}
}
?>
3️⃣ Controlador (UserController.php)
<?php
// app/controllers/UserController.php
require_once '../models/UserModel.php';
class UserController {
private $model;
public function __construct() {
$this->model = new UserModel();
}
public function index() {
$users = $this->model->getAllUsers();
require '../views/users/index.php';
}
public function show($id) {
$user = $this->model->getUserById($id);
if ($user) {
require '../views/users/show.php';
} else {
http_response_code(404);
echo "Usuario no encontrado";
}
}
}
?>
4️⃣ Vista (views/users/index.php)
<!-- app/views/users/index.php -->
<?php foreach ($users as $user): ?>
<div class="user-card">
<h3><?php echo htmlspecialchars($user['nombre']); ?></h3>
<p><?php echo htmlspecialchars($user['email']); ?></p>
</div>
<?php endforeach; ?>
Siempre usa htmlspecialchars() al mostrar datos del usuario
para prevenir ataques XSS. Nunca confíes en datos que vienen de la base de datos.
Seguridad en formularios y prevención de ataques
Con MVC, puedes centralizar la validación y sanitización en el controlador:
// En UserController.php
public function store() {
// Sanitizar y validar entrada
$email = filter_var($_POST['email'], FILTER_SANITIZE_EMAIL);
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$_SESSION['error'] = "Email inválido";
header("Location: /register");
exit;
}
// Hash de contraseña seguro
$password_hash = password_hash($_POST['password'], PASSWORD_DEFAULT);
// Usar prepared statement para prevenir SQL injection
$stmt = $this->conn->prepare("INSERT INTO users (email, password) VALUES (?, ?)");
$stmt->bind_param("ss", $email, $password_hash);
$stmt->execute();
// Redirigir con mensaje de éxito
$_SESSION['success'] = "Registro exitoso";
header("Location: /login");
}
Autenticación segura de usuarios con PHP y MySQLi
Almacena contraseñas con hash seguro y verifica con password_verify():
// Registrar usuario
$password_hash = password_hash($password, PASSWORD_DEFAULT);
// Verificar login
if (password_verify($password_input, $password_hash)) {
// Contraseña correcta: iniciar sesión
session_start();
$_SESSION['user_id'] = $user_id;
$_SESSION['rol'] = $user_rol;
} else {
// Contraseña incorrecta
$_SESSION['error'] = "Credenciales inválidas";
}
Manejo de sesiones en PHP
Usa sesiones para mantener al usuario autenticado entre páginas:
// Al inicio de cada página protegida
session_start();
if (!isset($_SESSION['user_id'])) {
// Usuario no autenticado: redirigir al login
header("Location: /login");
exit;
}
// Usuario autenticado: continuar con la lógica
$user_id = $_SESSION['user_id'];
$rol = $_SESSION['rol'] ?? 'user';
Tip: Regenera el ID de sesión después del login
con session_regenerate_id(true) para prevenir fijación de sesiones.
Uso del inspector del navegador para depuración
Aprende a usar las herramientas del navegador (F12) para depurar tu aplicación:
- Consola: Ver errores de JavaScript y logs con
console.log() - Network: Analizar peticiones AJAX y respuestas del servidor
- Application: Inspeccionar cookies, sesiones y almacenamiento local
- Elements: Depurar problemas de CSS y estructura HTML
Usa var_dump() o print_r() en PHP para ver el contenido
de variables, y error_log() para registrar errores sin mostrarlos al
usuario.
¿Qué sigue después de MVC?
Este es el sexto paso del desarrollo full-stack. En el siguiente módulo, aprenderás a enviar correos automáticos con PHPMailer, ideal para confirmaciones y recuperación de contraseña.
📚 ¿Quieres la versión completa del libro?
Esta guía es una versión resumida del libro "Programación Full-Stack", que incluye ejercicios resueltos, códigos listos y explicaciones profundas de arquitectura y seguridad.
Comprar en Amazon →¿Tienes dudas sobre MVC, seguridad o autenticación en PHP? ¡Déjalas en los comentarios! 👇