Módulo 1: Arquitectura Base (BD, Conexión y UI)
Todo software millonario inicia ordenando la casa. Aquí fundaremos la Base de Datos Total, la Conexión Inteligente (POO Singleton) y el Layout (Plantilla UI) Universal con Bootstrap.
1. El Diccionario Relacional (MySQL)
Ve a PHPMyAdmin en tu WAMP local y ejecuta esta estructura maestra completa.
$ MySQL Server
CREATE DATABASE academia_mvc;
USE academia_mvc;
CREATE TABLE usuarios (
id INT AUTO_INCREMENT PRIMARY KEY, nombre VARCHAR(100), correo VARCHAR(50) UNIQUE,
password VARCHAR(255), rol VARCHAR(20) DEFAULT 'ADMINISTRADOR'
);
-- 1. Insertamos Super-Admin (El hash significa "123")
INSERT INTO usuarios (nombre, correo, password) VALUES ('Súper Admin', 'admin@admin.com', '$2y$10$fV8g5Qv5J6O2HhS5aX.UaenM0TIt7D5qE/x1x2k/kP636R5Zk4wz2');
CREATE TABLE estudiantes (
id INT AUTO_INCREMENT PRIMARY KEY, matricula VARCHAR(20) UNIQUE, nombre VARCHAR(100), correo VARCHAR(50)
);
CREATE TABLE profesores (
id INT AUTO_INCREMENT PRIMARY KEY, nombre VARCHAR(100), especialidad VARCHAR(100)
);
CREATE TABLE cursos ( -- Relacion 1:N (1 Profe con Varios Cursos)
id INT AUTO_INCREMENT PRIMARY KEY, nombre VARCHAR(100),
id_profesor INT, FOREIGN KEY (id_profesor) REFERENCES profesores(id) ON DELETE CASCADE
);
CREATE TABLE matriculas ( -- Relacion N:M (El Estudiante puede entrar a Muchos Cursos)
id_estudiante INT, id_curso INT, PRIMARY KEY (id_estudiante, id_curso),
FOREIGN KEY (id_estudiante) REFERENCES estudiantes(id) ON DELETE CASCADE,
FOREIGN KEY (id_curso) REFERENCES cursos(id) ON DELETE CASCADE
);
2. La Conexión Irrompible a la BD (PDO Singleton)
Jamás debes escribir las claves de usuario de la DB en cada archivo mvc. Los profesionales hacen 1 archivo con patrón Singleton para reutilizar la conexión RAM sin saturar al servidor y usando anti-inyecciones `\PDO`.
app/Core/Database.php<?php
namespace App\Core;
class Database {
private static $instance = null;
private $pdo;
private function __construct() {
try {
$this->pdo = new \PDO("mysql:host=localhost;dbname=academia_mvc;charset=utf8", "root", "");
$this->pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
} catch (\PDOException $e) { die("MySQL Crash: " . $e->getMessage()); }
}
public static function getInstance() {
if (self::$instance === null) { self::$instance = new Database(); }
return self::$instance->pdo;
}
}
3. Recursos Locales y el Layout HTML (Bootstrap 5)
En MVC no escribimos 50 veces <!DOCTYPE html>. Programamos el Menú Visual (El Layout) solo 1 vez e inyectamos a PHP en el medio. Para que el proyecto funcione en velocidad máxima (y sin internet), descarga las dependencias y organízalas en tu WAMP.
3.1: Descargas Oficiales
3.2: Ubicar así en tu Proyecto:
📁 tu_proyecto/ 📁 assets/
📁 css/
📄 bootstrap.min.css
📄 sweetalert2.min.css
📁 js/
📄 bootstrap.bundle.min.js
📄 sweetalert2.all.min.js
Teniendo esos archivos en tus carpetas, crea este HTML en:
app/Views/layout/main.php<!DOCTYPE html>
<html lang="es" data-bs-theme="light">
<head>
<meta charset="UTF-8"><title><?= $titulo ?? 'Sistema MVC' ?></title>
<!-- Conectamos las Carpetas Locales de arriba! -->
<link href="/tu_proyecto/assets/css/bootstrap.min.css" rel="stylesheet">
<link href="/tu_proyecto/assets/css/sweetalert2.min.css" rel="stylesheet">
</head>
<body class="bg-light text-dark">
<!-- Un simple Nav Bar Master -->
<nav class="navbar navbar-dark bg-dark mb-4 px-4 shadow">
<a class="navbar-brand fw-bold" href="/">🚀 Sistema Universitario MVC</a>
<?php if(isset($_SESSION['usuario_rol'])): ?>
<div class="text-white">👤 <?= $_SESSION['usuario_nombre'] ?> <a href="/logout" class="btn btn-sm btn-danger ms-3">Salir</a></div>
<?php endif; ?>
</nav>
<!-- AQUI OCURRE LA MAGIA DEL CONTENEDOR (Lo que cambian son las Vistas hijas) -->
<main class="container mb-5">
<?php
// Inyectar los HTMLs hijos si el controlador lo pide
if(isset($view) && file_exists("app/Views/{$view}.php")) {
require_once "app/Views/{$view}.php";
}
?>
</main>
<!-- Los JS que van siempre al fondo del body! -->
<script src="/tu_proyecto/assets/js/bootstrap.bundle.min.js"></script>
<script src="/tu_proyecto/assets/js/sweetalert2.all.min.js"></script>
</body>
</html>