Módulo 6: Conceptos de Desarrollo Web

Proyecto final: Crea un blog en PHP con MVC

Lección 32 de 33 del Curso Roadmap Learning Laravel

Duración: 3 horas
Nivel: Principiante (requiere conocimientos de HTML, CSS, JavaScript, PHP básico, MySQL, SQL básico, protocolo HTTP, patrón MVC, configuración de entornos locales, y seguridad básica en PHP)
Objetivo: Desarrollar una aplicación PHP con patrón MVC básico (sin framework) para un blog, que permita listar publicaciones y crear nuevas publicaciones mediante un formulario, utilizando MySQL y aplicando validación de entradas, integrando los conceptos del Módulo 6.
Materiales necesarios:

  • Computadora con:
    • XAMPP o Laragon instalado (entorno local con Apache, PHP, MySQL, configurado en Lección 3).
    • Navegador web (Chrome, Firefox, etc.) con herramientas de desarrollo (DevTools, accesible con F12).
    • Editor de texto (recomendado: VS Code, descarga gratuita desde code.visualstudio.com).
    • Papel y lápiz para diagramas o notas.
  • Acceso a internet (para referencias).
    Contexto: Este proyecto final integra los conocimientos del Módulo 6:
  • Protocolo HTTP (Lección 1): Manejo de solicitudes GET y POST.
  • Patrón MVC (Lección 2): Organización del código en Modelo, Vista, Controlador.
  • Entornos locales (Lección 3): Uso de XAMPP o Laragon.
  • Seguridad (Lección 4): Validación de entradas y prevención de inyección SQL.
  • Módulos previos: Formularios PHP (Módulo 4), bases de datos MySQL (Módulo 5), y HTML/CSS (Módulo 2).
    El proyecto simula un blog básico, un caso práctico común que prepara para frameworks como Laravel.

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:

  1. 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).
  2. 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.
  3. 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).

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:

  1. 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);
    }
    ?>
  2. 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();
        }
    }
    ?>
  3. 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.");
            }
        }
    }
    ?>
  4. 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>
  5. 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; }
  6. 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:

  1. 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).
  2. 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.
  3. 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.

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:

  1. 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).
  2. 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.
  3. 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).
  4. 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.

© Copyright Cursos Laravel :: 2025 Términos y condiciones