Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/jpbarbatic/webapp/llms.txt

Use this file to discover all available pages before exploring further.

El panel implementa un sistema de plantillas propio basado en PHP puro. La plantilla maestra html/plantilla.html.php genera el documento HTML completo —cabecera, navegación, zona de contenido y scripts— e incluye dinámicamente los fragmentos específicos de cada vista. Este diseño elimina la duplicación de código: todos los controladores comparten el mismo esqueleto HTML y solo aportan los fragmentos que les son propios.

Cómo funciona

Cada controlador define la variable $vista con la ruta relativa (sin extensión) al subdirectorio html/ correspondiente a la vista que quiere mostrar. Por ejemplo, el listado de productos asigna:
$titulo = 'Productos';
$vista = 'productos/listado';
require('../../html/plantilla.html.php');
Al recibir $vista, la plantilla maestra busca y carga hasta tres fragmentos para esa vista, además de los componentes comunes: Fragmentos cargados por la plantilla:
// En <head>: estilos específicos de la vista (opcional)
<?php if (file_exists(__DIR__.'/'.$vista . ".css.php")) {
    include __DIR__.'/'.$vista . ".css.php";
} ?>

// En <body>: barra de navegación (siempre presente)
<?php include "nav.html.php" ?>

// En <main>: markup del contenido principal (siempre se intenta incluir)
<?php if (file_exists(__DIR__.'/'.$vista . ".html.php")) {
    include __DIR__.'/'.$vista . ".html.php";
} ?>

// Antes de </body>: scripts compartidos (incluido siempre; actualmente vacío)
<?php include __DIR__.'/comun.script.php'; ?>

// Antes de </body>: JavaScript específico de la vista (opcional)
<?php if (file_exists(__DIR__.'/'.$vista . ".script.php")) {
    include __DIR__.'/'.$vista . ".script.php";
} ?>
La plantilla usa file_exists() para verificar la existencia de los fragmentos opcionales antes de incluirlos, de modo que una vista sin estilos propios o sin JavaScript específico no genera ningún error. La barra de navegación (html/nav.html.php) también recibe $vista para marcar el elemento activo del menú, comparando el prefijo de $vista con el nombre del módulo:
<a class="nav-link<?= str_starts_with($vista, 'productos') ? ' active':'' ?>"
   href="productos/">Productos</a>

Mensajes flash

El sistema de mensajes flash permite que un controlador comunique el resultado de una operación (guardar, borrar, etc.) a la siguiente petición usando sesión. La plantilla lee dos claves de $_SESSION['mensaje'] y renderiza alertas Bootstrap:
<?php if (isset($_SESSION['mensaje']['ok'])): ?>
    <div class="alert alert-success alert-dismissible fade show" role="alert">
        <?= $_SESSION['mensaje']['ok'] ?>
        <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
    </div>
<?php endif; ?>
<?php if (isset($_SESSION['mensaje']['ko'])): ?>
    <div class="alert alert-danger alert-dismissible fade show" role="alert">
        <?= $_SESSION['mensaje']['ko'] ?>
        <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
    </div>
<?php endif; ?>
  • $_SESSION['mensaje']['ok'] — Alerta verde (alert-success) para operaciones completadas con éxito.
  • $_SESSION['mensaje']['ko'] — Alerta roja (alert-danger) para errores o validaciones fallidas.
Al final del fichero, una vez generado el HTML completo, la plantilla limpia el mensaje para que no vuelva a mostrarse en la siguiente petición:
<?php unset($_SESSION['mensaje']);?>
public/login.php guarda el mensaje de error de credenciales incorrectas como una cadena plana: $_SESSION['mensaje'] = 'Usuario y/o contraseña incorrectos'. El formulario de login (html/login.html.php) gestiona este caso directamente, ya que la plantilla maestra no interviene en la página de login.

Convenciones de nomenclatura

Cada vista puede componerse de hasta tres ficheros dentro de html/, todos con el mismo nombre base y sufijos diferentes:
SufijoUbicación en el HTMLPropósito
.html.phpDentro de <main class="container">Markup del contenido principal de la vista (tablas, formularios, tarjetas, etc.)
.css.phpDentro de <head>, tras los estilos globalesEstilos CSS exclusivos de la vista, incrustados como <style> o como <link> adicional
.script.phpAntes de </body>, tras los scripts globalesJavaScript exclusivo de la vista (inicialización de plugins, validaciones, llamadas AJAX, etc.)
Por ejemplo, para la vista productos/listado los tres ficheros serían:
html/
└── productos/
    ├── listado.html.php    ← markup de la tabla de productos
    ├── listado.css.php     ← estilos específicos (opcional)
    └── listado.script.php  ← scripts específicos (opcional)

Activos estáticos

La plantilla carga los siguientes activos desde el directorio public/assets/:
  • Bootstrap 5 CSSassets/bootstrap/dist/css/bootstrap.min.css
  • Bootstrap 5 JS Bundleassets/bootstrap/dist/js/bootstrap.bundle.min.js (incluye Popper.js)
  • Dashboard CSSassets/dashboard.css, hoja de estilos personalizada del panel
Los estilos de vista específicos (.css.php) se inyectan en el <head> después de dashboard.css, respetando así el orden de cascada de CSS y permitiendo que cada vista sobrescriba estilos globales si es necesario. La etiqueta <base href="<?= URL_BASE ?>"> en el <head> garantiza que todas las URLs relativas del HTML (enlaces, imágenes, formularios) se resuelvan correctamente con independencia de la profundidad del módulo actual.
Al tener la etiqueta <base>, los fragmentos de vista pueden usar rutas relativas a la raíz del panel (p. ej. href="productos/") en lugar de rutas relativas al fichero PHP del controlador, lo que simplifica el código de las vistas.

Ejemplo completo de controlador

El patrón estándar de un controlador que usa la plantilla es:
<?php
// 1. (Opcional) Declarar el permiso requerido antes del guard
$permiso = 'productos.consulta';

// 2. Incluir el guard: inicia sesión, verifica auth, abre DB
$db = require_once('../../includes/backend.php');

// 3. Lógica de negocio: consultas, procesado de datos
$titulo = 'Productos';
$datos  = db_query($db, 'SELECT * FROM productos ORDER BY nombre');

// 4. Preparar las variables de plantilla
$vista = 'productos/listado';

// 5. Delegar el renderizado a la plantilla maestra
require('../../html/plantilla.html.php');
La separación entre pasos 3–4 y el paso 5 garantiza que todo el procesado de datos ocurre antes de que comience la generación de HTML, lo que simplifica el depurado y evita problemas con cabeceras HTTP ya enviadas.

Build docs developers (and LLMs) love