Introducción al proyecto final (15 minutos)
Explicación:
El proyecto final es una aplicación PHP que implementa un blog básico con patrón MVC (sin framework). La aplicación permitirá:
- Listar publicaciones: Mostrar una lista de publicaciones almacenadas en MySQL (solicitud GET).
- Crear publicaciones: Usar un formulario para añadir nuevas publicaciones (solicitud POST).
- Seguridad: Validar entradas y usar consultas preparadas para prevenir inyección SQL.
Requisitos:
- Base de datos: Una tabla para almacenar publicaciones (título, contenido, fecha).
- Estructura MVC:
- Modelo: Gestionar datos (consultas SQL).
- Vista: Mostrar publicaciones y formulario (HTML/CSS).
- Controlador: Procesar solicitudes (GET para listar, POST para crear).
- Validación: Asegurar que los datos del formulario sean válidos y seguros.
- Entorno: XAMPP o Laragon para probar localmente.
Por qué es importante:
- Integra todos los conceptos del Módulo 6 en una aplicación funcional.
- Consolida habilidades de Módulo 4 (formularios PHP) y Módulo 5 (MySQL).
- Prepara para Laravel, que usa MVC, validación, y bases de datos de forma similar.
Punto clave: El proyecto final demuestra la capacidad de desarrollar una aplicación web estructurada y segura.
Actividad rápida (3 minutos):
Escribe en papel las dos funcionalidades principales del blog y el verbo HTTP asociado.
- Ejemplo:
- Funcionalidad: Listar publicaciones → Verbo: GET.
- Funcionalidad: Crear publicación → Verbo: POST.
Diseño del proyecto y configuración inicial (30 minutos)
Explicación:
Diseñaremos la estructura del proyecto, configuraremos la base de datos, y prepararemos el entorno local.
Estructura del proyecto:
/blog_app
/models
PublicacionModel.php
/views
listar_view.php
crear_view.php
/controllers
PublicacionController.php
/assets
styles.css
index.php
config.php
Base de datos:
- Nombre: blog_db.
- Tabla: publicaciones.
- SQL:
CREATE DATABASE blog_db; USE blog_db; CREATE TABLE publicaciones ( id INT AUTO_INCREMENT PRIMARY KEY, titulo VARCHAR(200) NOT NULL, contenido TEXT NOT NULL, fecha_creacion DATETIME DEFAULT CURRENT_TIMESTAMP ); INSERT INTO publicaciones (titulo, contenido) VALUES ('Primera publicación', '¡Bienvenidos a mi blog! Este es el primer post.'), ('PHP y MVC', 'Aprendiendo a estructurar aplicaciones con MVC.');
Configuración del entorno:
- Entorno local:
- Asegúrate de que XAMPP o Laragon esté instalado (Lección 3).
- Inicia Apache y MySQL.
- Verifica: http://localhost (XAMPP) o http://localhost (Laragon).
- Base de datos:
- Abre http://localhost/phpmyadmin.
- Crea la base de datos blog_db y la tabla publicaciones.
- Ejecuta el SQL para insertar datos de prueba.
- Carpeta del proyecto:
- Crea la carpeta blog_app en:
- XAMPP: C:\xampp\htdocs\blog_app.
- Laragon: C:\laragon\www\blog_app.
- Configura la estructura de carpetas (models, views, controllers, assets).
- Crea la carpeta blog_app en:
Punto clave: Una estructura MVC clara y una base de datos configurada son la base del proyecto.
Actividad rápida (5 minutos):
Crea la carpeta blog_app en tu entorno local (XAMPP o Laragon) y escribe en papel la estructura de carpetas.
- Ejemplo:
/blog_app /models /views /controllers /assets index.php config.php
Desarrollo del proyecto: Implementación MVC (90 minutos)
Explicación:
Implementaremos la aplicación blog con MVC básico, incluyendo:
- Modelo: Consultas para listar y crear publicaciones.
- Vista: Páginas para mostrar publicaciones y un formulario.
- Controlador: Lógica para manejar solicitudes GET y POST.
- Seguridad: Validación de entradas y consultas preparadas (Lección 4).
Código del proyecto:
- Configuración (config.php):
- Conexión a MySQL.
<?php $host = 'localhost'; $usuario = 'root'; $contrasena = ''; // Vacío en XAMPP/Laragon por defecto $base_datos = 'blog_db'; $conexion = new mysqli($host, $usuario, $contrasena, $base_datos); if ($conexion->connect_error) { die("Error de conexión: " . $conexion->connect_error); } ?>
- Modelo (models/PublicacionModel.php):
- Gestiona consultas a la tabla publicaciones.
<?php class PublicacionModel { private $conexion; public function __construct($conexion) { $this->conexion = $conexion; } public function listarPublicaciones() { $query = "SELECT id, titulo, contenido, fecha_creacion FROM publicaciones ORDER BY fecha_creacion DESC"; $resultado = $this->conexion->query($query); $publicaciones = []; while ($fila = $resultado->fetch_assoc()) { $publicaciones[] = $fila; } return $publicaciones; } public function crearPublicacion($titulo, $contenido) { $stmt = $this->conexion->prepare("INSERT INTO publicaciones (titulo, contenido) VALUES (?, ?)"); $stmt->bind_param("ss", $titulo, $contenido); return $stmt->execute(); } } ?>
- Controlador (controllers/PublicacionController.php):
- Maneja solicitudes y conecta Modelo y Vista.
<?php require_once 'models/PublicacionModel.php'; class PublicacionController { private $modelo; public function __construct($conexion) { $this->modelo = new PublicacionModel($conexion); } public function listar() { $publicaciones = $this->modelo->listarPublicaciones(); require 'views/listar_view.php'; } public function mostrarFormulario() { require 'views/crear_view.php'; } public function crear() { $titulo = trim($_POST['titulo'] ?? ''); $contenido = trim($_POST['contenido'] ?? ''); // Validación de entradas if (empty($titulo) || strlen($titulo) > 200) { die("Error: El título es obligatorio y debe tener menos de 200 caracteres."); } if (empty($contenido)) { die("Error: El contenido es obligatorio."); } // Escapar datos para seguridad $titulo = htmlspecialchars($titulo); $contenido = htmlspecialchars($contenido); // Guardar publicación if ($this->modelo->crearPublicacion($titulo, $contenido)) { header("Location: index.php?accion=listar"); exit; } else { die("Error al crear la publicación."); } } } ?>
- Vistas:
- Listar publicaciones (views/listar_view.php):
<!DOCTYPE html> <html lang="es"> <head> <meta charset="UTF-8"> <title>Blog - Publicaciones</title> <link rel="stylesheet" href="assets/styles.css"> </head> <body> <h1>Mi Blog</h1> <a href="index.php?accion=crear">Crear nueva publicación</a> <h2>Publicaciones</h2> <?php if (empty($publicaciones)): ?> <p>No hay publicaciones.</p> <?php else: ?> <?php foreach ($publicaciones as $pub): ?> <div class="publicacion"> <h3><?php echo htmlspecialchars($pub['titulo']); ?></h3> <p><?php echo htmlspecialchars($pub['contenido']); ?></p> <small>Publicado el: <?php echo $pub['fecha_creacion']; ?></small> </div> <?php endforeach; ?> <?php endif; ?> </body> </html>
- Formulario para crear (views/crear_view.php):
<!DOCTYPE html> <html lang="es"> <head> <meta charset="UTF-8"> <title>Blog - Nueva Publicación</title> <link rel="stylesheet" href="assets/styles.css"> </head> <body> <h1>Mi Blog</h1> <a href="index.php?accion=listar">Volver a la lista</a> <h2>Crear Publicación</h2> <form action="index.php?accion=guardar" method="POST"> <label>Título: <input type="text" name="titulo" required></label><br> <label>Contenido: <textarea name="contenido" required></textarea></label><br> <button type="submit">Guardar</button> </form> </body> </html>
- Listar publicaciones (views/listar_view.php):
- Estilos (assets/styles.css):
- Estilo básico para la interfaz.
body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; } h1 { color: #333; } .publicacion { border: 1px solid #ccc; padding: 10px; margin: 10px 0; } label { display: block; margin: 10px 0; } input, textarea { width: 100%; padding: 8px; margin: 5px 0; } button { padding: 10px 20px; background-color: #007BFF; color: white; border: none; cursor: pointer; } button:hover { background-color: #0056b3; } a { color: #007BFF; text-decoration: none; } a:hover { text-decoration: underline; }
- Punto de entrada (index.php):
- Enruta solicitudes al Controlador.
<?php require_once 'config.php'; require_once 'controllers/PublicacionController.php'; $controlador = new PublicacionController($conexion); $accion = $_GET['accion'] ?? 'listar'; switch ($accion) { case 'listar': $controlador->listar(); break; case 'crear': $controlador->mostrarFormulario(); break; case 'guardar': $controlador->crear(); break; default: $controlador->listar(); } ?>
Cómo probarlo:
- Configuración:
- Asegúrate de que XAMPP o Laragon esté corriendo (Apache y MySQL).
- Crea la base de datos blog_db y la tabla publicaciones en phpMyAdmin (http://localhost/phpmyadmin).
- Inserta los datos de prueba (SQL proporcionado).
- Guarda todos los archivos en C:\xampp\htdocs\blog_app (XAMPP) o C:\laragon\www\blog_app (Laragon).
- Pruebas:
- Abre http://localhost/blog_app/index.php (XAMPP) o http://blog_app.test (Laragon).
- Listar publicaciones:
- Deberías ver las dos publicaciones de prueba (“Primera publicación”, “PHP y MVC”).
- Verifica en DevTools (F12, pestaña “Red”): Solicitud GET, código 200 OK.
- Crear publicación:
- Haz clic en “Crear nueva publicación”.
- Completa el formulario (por ejemplo, Título: “Mi nuevo post”, Contenido: “Contenido de prueba”).
- Envía: Redirige a la lista, mostrando la nueva publicación.
- Prueba entradas inválidas:
- Título vacío → Mensaje: “El título es obligatorio…”.
- Título largo (>200 caracteres) → Mensaje de error.
- Verifica en DevTools: Solicitud POST a index.php?accion=guardar, código 200 OK.
- Seguridad:
- Intenta una inyección SQL (por ejemplo, Título: '; DROP TABLE publicaciones; --):
- La consulta preparada neutraliza el ataque.
- Los datos están validados y escapados con htmlspecialchars() para prevenir XSS.
- Intenta una inyección SQL (por ejemplo, Título: '; DROP TABLE publicaciones; --):
Flujo MVC:
- Listar:
- Solicitud GET → index.php?accion=listar → PublicacionController::listar() → PublicacionModel::listarPublicaciones() → listar_view.php.
- Crear:
- Solicitud GET → index.php?accion=crear → PublicacionController::mostrarFormulario() → crear_view.php.
- Solicitud POST → index.php?accion=guardar → PublicacionController::crear() → PublicacionModel::crearPublicacion() → Redirige a listar.
Por qué es importante:
- Combina MVC (Lección 2), HTTP (Lección 1), seguridad (Lección 4), y MySQL (Módulo 5).
- Prepara para Laravel, donde usarás rutas, controladores, modelos Eloquent, y vistas Blade.
Punto clave: La aplicación blog demuestra cómo estructurar y securizar una aplicación PHP con MVC.
Actividad rápida (5 minutos):
Escribe en papel un archivo del proyecto y su rol (Modelo, Vista, o Controlador).
- Ejemplo:
- Archivo: PublicacionModel.php.
- Rol: Modelo (gestiona consultas SQL).
Resumen y entrega del proyecto (45 minutos)
Resumen:
- Proyecto: Blog PHP con MVC básico (sin framework).
- Funcionalidades:
- Listar publicaciones (GET, muestra datos de MySQL).
- Crear publicaciones (POST, formulario con validación).
- Componentes:
- Modelo: Consultas preparadas para listar y crear.
- Vista: HTML/CSS para interfaz.
- Controlador: Manejo de solicitudes HTTP.
- Seguridad: Validación de entradas, consultas preparadas, escaping para XSS.
- Entorno: XAMPP o Laragon (Lección 3).
Entrega del proyecto:
- Entregable: Una aplicación funcional con estructura MVC, incluyendo:
- Carpeta blog_app con todos los archivos (models, views, controllers, assets, index.php, config.php).
- Base de datos blog_db con la tabla publicaciones y datos de prueba.
- Un archivo de texto o documento (proyecto_final.txt o .docx) con:
- Descripción del proyecto (qué hace).
- Instrucciones para ejecutarlo (por ejemplo, “Copiar a htdocs, crear base de datos…”).
- Estructura de carpetas y archivos.
- SQL de la base de datos.
- Explicación breve de cada componente MVC.
- Resultados de pruebas (por ejemplo, “Listé publicaciones, creé un post”).
- Opcional: Capturas de pantalla (lista de publicaciones, formulario, phpMyAdmin).
Instrucciones para el entregable:
- Implementar:
- Copia el código proporcionado en las carpetas correspondientes.
- Configura la base de datos en phpMyAdmin.
- Prueba la aplicación en XAMPP (http://localhost/blog_app) o Laragon (http://blog_app.test).
- Documentar:
- Crea proyecto_final.txt o .docx con la información solicitada.
- Ejemplo de contenido:
Proyecto Final: Blog con MVC en PHP Descripción: Una aplicación PHP que permite listar publicaciones y crear nuevas usando MVC, MySQL, y validación de entradas. Instrucciones: 1. Copiar la carpeta blog_app a C:\xampp\htdocs (XAMPP) o C:\laragon\www (Laragon). 2. Crear la base de datos blog_db en phpMyAdmin y ejecutar el SQL proporcionado. 3. Abrir http://localhost/blog_app (XAMPP) o http://blog_app.test (Laragon). 4. Probar listar publicaciones y crear una nueva. Estructura: /blog_app /models PublicacionModel.php /views listar_view.php crear_view.php /controllers PublicacionController.php /assets styles.css index.php config.php SQL: CREATE DATABASE blog_db; CREATE TABLE publicaciones ( id INT AUTO_INCREMENT PRIMARY KEY, titulo VARCHAR(200) NOT NULL, contenido TEXT NOT NULL, fecha_creacion DATETIME DEFAULT CURRENT_TIMESTAMP ); INSERT INTO publicaciones (titulo, contenido) VALUES ('Primera publicación', '¡Bienvenidos a mi blog!'), ('PHP y MVC', 'Aprendiendo MVC.'); Componentes MVC: - Modelo (PublicacionModel.php): Consulta y guarda publicaciones en MySQL con consultas preparadas. - Vista (listar_view.php, crear_view.php): Muestra publicaciones y formulario HTML. - Controlador (PublicacionController.php): Maneja solicitudes GET/POST, valida entradas. Resultados: - Listé las publicaciones iniciales correctamente. - Creé una publicación con título “Test” y contenido “Prueba”. Redirigió a la lista. - Probé entradas inválidas (título vacío): Mostró error correctamente.
- Probar exhaustivamente:
- Verifica ambas funcionalidades (listar, crear).
- Prueba casos límite: Título vacío, contenido largo, posibles inyecciones SQL.
- Usa DevTools para confirmar solicitudes HTTP (GET, POST) y códigos de estado (200 OK, 302 para redirección).
- Entregar:
- Comprime la carpeta blog_app (ZIP o RAR).
- Incluye proyecto_final.txt o .docx.
- Opcional: Añade capturas de pantalla.
Tiempo estimado:
- Configuración y desarrollo: ~2 horas.
- Pruebas y documentación: ~1 hora.
Consejo:
- Sigue el código proporcionado para evitar errores.
- Prueba en un entorno limpio (nueva carpeta en htdocs o www).
- Revisa los logs de XAMPP/Laragon si hay errores (C:\xampp\apache\logs o C:\laragon\logs).
Punto clave: El entregable demuestra dominio de MVC, seguridad, y desarrollo web con PHP.