MVC Master

Módulo 7: Máximo Boss Múltiple (Matrículas N:M)

Esta es la interfaz cumbre del estudiante. Vamos a inscribir a 1 Alumno a 5 CURSOS MATERIAS a la vez mediante un Array, y a mostrar la inmensa lista de cobros usando una Tabla Cruzada Triple Vía. Igualito a como se ve en la "Demo App" Viva de tu sistema.

7.1: El Modelo Crítico Pivote N:M

app/Models/MatriculaModelo.php
<?php
namespace App\Models;

class MatriculaModelo {
    private $db;
    public function __construct() { $this->db = \App\Core\Database::getInstance(); }
    
    public function crearCruce($idestudio, $idcurso) {
        // Truco Maestro PRO: "INSERT IGNORE" evita Pantallazo Naranja si el alumno repite mismo curso
        $sql = "INSERT IGNORE INTO matriculas (id_estudiante, id_curso) VALUES (:e, :c)";
        try {
            return $this->db->prepare($sql)->execute(['e'=>$idestudio, 'c'=>$idcurso]);
        } catch(\PDOException $e) { return false; }
    }

    public function listadoTotal() {
        $sql = "SELECT m.id_estudiante, e.nombre as estudiante, e.matricula, c.nombre as curso 
                FROM matriculas m 
                JOIN estudiantes e ON m.id_estudiante = e.id 
                JOIN cursos c ON m.id_curso = c.id";
        return $this->db->query($sql)->fetchAll(\PDO::FETCH_OBJ);
    }
}

7.2: Controlador Transaccional

app/Controllers/DemoController.php
    public function matriculas() {
        $this->render('matriculas/index', [
            'lista_matr' => (new \App\Models\MatriculaModelo())->listadoTotal()
        ]);
    }

    public function crearMatricula() {
        $this->render('matriculas/crear', [
            'estudiantes' => (new \App\Models\EstudianteModelo())->all(), 
            'cursos' => (new \App\Models\CursoModelo())->all()
        ]);
    }

    public function guardarMatricula() {
        $inscriptor = new \App\Models\MatriculaModelo();
        // ESTE BUCLE FOREACH ES EL QUE RECIBE EL SELECT[] MÚLTIPLE HTML
        foreach($_POST['cursos_array_del_front'] as $mat) {
            $inscriptor->crearCruce($_POST['id_est'], $mat);
        }
        header("Location: " . BASE_URL . "/demo/matriculas"); exit;
    }

7.3: La Vista Listado y el Formulario Multi-Ticket

app/Views/matriculas/index.php
<div class="card border-0 shadow-sm p-4">
    <div class="d-flex justify-content-between mb-4">
        <h2>Central de Ventas</h2>
        <a href="/demo/matriculas/crear" class="btn btn-success">Facturar Combinación</a>
    </div>
    <table class="table">
        <thead><tr><th>CLIENTE BD</th><th>PRODUCTO COMPRADO</th></tr></thead>
        <tbody>
            <?php foreach($lista_matr as $reg): ?>
            <tr>
                <td class="fw-bold">[COD-<?= $reg->matricula ?>] <?= $reg->estudiante ?></td>
                <td class="text-success"><?= $reg->curso ?></td>
            </tr>
            <?php endforeach; ?>
        </tbody>
    </table>
</div>
app/Views/matriculas/crear.php
<div class="container d-flex justify-content-center mt-3">
    <div class="card shadow-sm border-0 p-5 bg-white w-50" style="border-radius:15px;">
        <form action="/demo/matriculas/guardar" method="POST">
            
            <label class="fw-bold fs-5 text-primary">1. Elige al Cliente</label>
            <select name="id_est" class="form-select border-primary shadow-sm mb-4" required>
                <?php foreach($estudiantes as $est): ?>
                    <option value="<?= $est->id ?>"><?= $est->nombre ?></option>  
                <?php endforeach; ?>
            </select>

            <label class="fw-bold fs-5 text-success">2. Array Múltiple de Compra</label>
            <select name="cursos_array_del_front[]" class="form-select border-success shadow-sm" multiple style="height:210px;" required>
                <?php foreach($cursos as $cur): ?>
                    <option value="<?= $cur->id ?>">🛒 <?= $cur->nombre ?></option>
                <?php endforeach; ?>
            </select>
            
            <button type="submit" class="btn btn-success fw-bold w-100 py-3 mt-4">PROCESAR CARRO MULTIPLE</button>
        </form>
    </div>
</div>