🎮 Controladores - Plugin Coches
Gestionan la lógica de negocio y las interacciones del usuario con los vehículos
📋 Controladores del Plugin Coches
EditCoche.php
Controlador para crear y editar vehículos individuales
EditControllerListCoche.php
Controlador para listar, buscar y gestionar múltiples vehículos
ListController✏️ EditCoche.php - Controlador de Edición
<?php
namespace FacturaScripts\Plugins\Coches\Controller;
use FacturaScripts\Core\Lib\ExtendedController\EditController;
class EditCoche extends EditController
{
public function getModelClassName(): string
{
return 'Coche';
}
}
🎯 Simplicidad y Eficiencia
Este controlador es minimalista porque hereda toda la funcionalidad de EditController:
- Creación automática de formularios desde vistas XML
- Validación de datos integrada según el modelo
- Guardado y actualización automáticos con transacciones
- Manejo de errores y mensajes al usuario
- Integración automática con vistas XML del modelo
🔗 Conexión con el Modelo
El método getModelClassName() es crucial:
- Define qué modelo gestiona este controlador:
'Coche' - Permite la comunicación automática con la base de datos
- Habilita las operaciones CRUD básicas automáticamente
- Conecta con la vista XML correspondiente (
EditCoche.xml) - Establece las reglas de validación según las propiedades del modelo
📋 ListCoche.php - Controlador de Listado
<?php
namespace FacturaScripts\Plugins\Coches\Controller;
use FacturaScripts\Core\Lib\ExtendedController\ListController;
use FacturaScripts\Dinamic\Model\Coche;
use FacturaScripts\Core\Tools;
class ListCoche extends ListController
{
public function getPageData(): array
{
$page = parent::getPageData();
$page['title'] = 'Coches';
$page['menu'] = 'Coches';
$page['icon'] = 'fas fa-search';
return $page;
}
protected function createViews()
{
$this->addView('ListCoche', 'coche', 'coche', 'fas fa-car')
->addOrderBy(['idcoche'], 'Creacion', 2)
->addSearchFields(['matricula', 'marca', 'modelo']);
$this->setSettings('ListCoche', 'modalInsert', 'modalCoche');
$this->addButton('ListCoche',[
'action' => 'siniestro',
'type' => 'action',
'icon' => 'fas fa-exclamation-triangle',
'label' => 'Baja',
'color' => 'danger',
'confirm' => true,
]);
$this->addButton('ListCoche',[
'action' => 'fechaitv',
'type' => 'modal',
'icon' => 'fas fa-exclamation-triangle',
'label' => 'ITV',
'color' => 'warning',
'confirm' => true,
]);
}
protected function execPreviousAction($action)
{
switch($action){
case 'siniestro':
$this->siniestro();
break;
case 'fechaitv':
$this->fechaitv();
break;
case 'modalCoche':
$this->modalCoche();
break;
}
return parent::execPreviousAction($action);
}
protected function siniestro()
{
$codes = $this->request->request->getArray('codes');
if (empty($codes)){
Tools::log()->warning('No se han seleccionado coches para marcar como siniestro.');
return;
}
foreach ($codes as $code) {
$coche = new Coche();
$coche = $coche->find($code);
$coche->siniestro=true;
$coche->save();
Tools::log()->notice('Marcado como siniestro los coches seleccionados.');
}
}
protected function fechaitv()
{
$codes = $this->request->request->getArray('codes');
if (empty($codes)){
Tools::log()->warning('No se han seleccionado coches para cambiar la ITV.');
return;
}
foreach ($codes as $code) {
$coche = new Coche();
$coche = $coche->find($code);
$coche->fechaitv = $this->request->request->get('fechaitv');
$coche->save();
Tools::log()->notice('ITV cambiada de los coches seleccionados.');
}
}
protected function modalCoche()
{
$coche = new Coche();
$coche->matricula = $this->request->request->get('matricula');
$coche->marca = $this->request->request->get('marca');
$coche->modelo = $this->request->request->get('modelo');
$coche->fechaitv = $this->request->request->get('fechaitv');
$coche->siniestro = false;
$coche->save();
Tools::log()->notice('Vehículo creado con éxito.');
}
}
🔍 Análisis de ListCoche.php
📊 getPageData() - Configuración de Página
public function getPageData(): array
{
$page = parent::getPageData();
$page[\'title\'] = \'Coches\';
$page[\'menu\'] = \'Coches\';
$page[\'icon\'] = \'fas fa-search\';
return $page;
}
Función: Configura los metadatos de la página del controlador
title: 'Coches' - Título que aparece en el navegadormenu: 'Coches' - Menú donde aparece la opción en FacturaScriptsicon: 'fas fa-search' - Icono de FontAwesome para el menúparent::getPageData(): Obtiene configuración base del controlador padre
👁️ createViews() - Configuración de Vistas
protected function createViews()
{
$this->addView(\'ListCoche\', \'coche\', \'coche\', \'fas fa-car\')
->addOrderBy([\'idcoche\'], \'Creacion\', 2)
->addSearchFields([\'matricula\', \'marca\', \'modelo\']);
$this->setSettings(\'ListCoche\', \'modalInsert\', \'modalCoche\');
$this->addButton(\'ListCoche\',[
\'action\' => \'siniestro\',
\'type\' => \'action\',
\'icon\' => \'fas fa-exclamation-triangle\',
\'label\' => \'Baja\',
\'color\' => \'danger\',
\'confirm\' => true,
]);
$this->addButton(\'ListCoche\',[
\'action\' => \'fechaitv\',
\'type\' => \'modal\',
\'icon\' => \'fas fa-exclamation-triangle\',
\'label\' => \'ITV\',
\'color\' => \'warning\',
\'confirm\' => true,
]);
}
Parámetros de addView:
- ViewName: 'ListCoche' - Nombre interno de la vista
- ModelName: 'coche' - Nombre del modelo (en minúsculas)
- ViewTitle: 'coche' - Título que ven los usuarios
- ViewIcon: 'fas fa-car' - Icono de la vista
Configuraciones adicionales:
addOrderBy(): Campos para ordenar (idcoche por creación)addSearchFields(): Campos para búsqueda (matrícula, marca, modelo)setSettings(): Configura modal para inserción rápidaaddButton(): Añade botones de acción personalizados
⚡ execPreviousAction() - Acciones Personalizadas
protected function execPreviousAction($action){
switch($action){
case "siniestro":
$this->siniestro();
break;
case "fechaitv":
$this->fechaitv();
break;
case "modalCoche":
$this->modalCoche();
break;
}
return parent::execPreviousAction($action);
}
Función: Maneja acciones personalizadas desde los botones de la vista
Flujo de ejecución:
- El usuario hace clic en un botón de acción en la vista XML
- Se ejecuta
execPreviousAction()con el nombre de la acción - El switch detecta la acción y llama al método correspondiente
- Si no hay coincidencia, delega al padre con
parent::execPreviousAction() - Los métodos llamados procesan la lógica específica
🛠️ Acciones Personalizadas del Controlador
🚨 siniestro() - Marcar como Baja
protected function siniestro()
{
$codes = $this->request->request->getArray(\'codes\');
if (empty($codes)){
Tools::log()->warning(\'No se han seleccionado coches...\');
return;
}
foreach ($codes as $code) {
$coche = new Coche();
$coche = $coche->find($code);
$coche->siniestro=true;
$coche->save();
}
Tools::log()->notice(\'Marcado como siniestro...\');
}
Función: Marca los vehículos seleccionados como siniestrados
Flujo de ejecución:
- Obtiene los IDs seleccionados con
getArray('codes') - Valida que haya selección, si no, muestra warning
- Para cada ID: crea instancia, busca el coche, marca siniestro=true
- Guarda cada cambio con
save() - Registra mensaje de éxito en el log del sistema
confirm: true pide confirmación antes de ejecutar
📅 fechaitv() - Cambiar Fecha ITV
protected function fechaitv()
{
$codes = $this->request->request->getArray(\'codes\');
if (empty($codes)){
Tools::log()->warning(\'No se han seleccionado coches...\');
return;
}
foreach ($codes as $code) {
$coche = new Coche();
$coche = $coche->find($code);
$coche->fechaitv = $this->request->request->get(\'fechaitv\');
$coche->save();
}
Tools::log()->notice(\'ITV cambiada...\');
}
Función: Actualiza la fecha ITV de vehículos seleccionados
Flujo de ejecución:
- Obtiene los IDs seleccionados
- Valida selección
- Para cada ID: busca coche, actualiza fecha ITV desde request
- Guarda cambios
- Registra en log
modal - abre ventana emergente para ingresar fecha
🚗 modalCoche() - Creación Rápida
protected function modalCoche()
{
$coche = new Coche();
$coche->matricula = $this->request->request->get(\'matricula\');
$coche->marca = $this->request->request->get(\'marca\');
$coche->modelo = $this->request->request->get(\'modelo\');
$coche->fechaitv = $this->request->request->get(\'fechaitv\');
$coche->siniestro = false;
$coche->save();
Tools::log()->notice(\'Vehículo creado con éxito.\');
}
Función: Crea un nuevo vehículo desde modal de inserción rápida
Flujo de ejecución:
- Crea nueva instancia de Coche
- Asigna valores desde el formulario modal
- Establece
siniestro = falsepor defecto - Guarda el nuevo registro
- Registra mensaje de éxito
🔗 Integración con Vistas XML
ListCoche.php
ListCoche.xml
de Usuario
Final
Conexión Botones → Acciones
Vista XML - Botón de Acción
<button action="siniestro"
color="danger"
icon="fas fa-exclamation-triangle"
label="Baja"
type="action"
confirm="true"/>
Controlador PHP - Switch Case
case "siniestro":
$this->siniestro();
break;
Conectores automáticos: El atributo action en el botón XML se conecta automáticamente con el case correspondiente en execPreviousAction().
Configuración de Modal de Inserción
Controlador PHP - Configuración
$this->setSettings(\'ListCoche\',
\'modalInsert\',
\'modalCoche\');
Vista XML - Definición del Modal
<modals>
<group name="modalCoche"
title="Modelo de Coche"
icon="fas fa-car">
<!-- campos del modal -->
</group>
</modals>
Integración automática: El controlador configura qué modal usar para inserción rápida, y la vista XML define la estructura del modal.
🎯 Buenas Prácticas Implementadas
🔒 Validación de Datos
Todas las acciones validan la entrada antes de procesar:
if (empty($codes)){
Tools::log()->warning(\'No se han seleccionado...\');
return;
}
Evita errores y proporciona feedback al usuario.
📝 Logs Informativos
Uso consistente del sistema de logs de FacturaScripts:
Tools::log()->warning(\'Mensaje de advertencia\');
Tools::log()->notice(\'Mensaje informativo\');
Tools::log()->error(\'Mensaje de error\');
Facilita debugging y seguimiento de operaciones.
🔄 Gestión de Errores
Patrón de early return para manejar errores:
if ($condicionError) {
Tools::log()->warning(\'Error detectado\');
return; // Sale temprano sin ejecutar más código
}
// Código normal aquí...
Mantiene el código limpio y fácil de leer.
⚠️ Problemas Comunes y Soluciones
Acciones no se ejecutan
Causa: Nombre de acción no coincide entre XML y PHP
Solución: Verificar que action="nombre" en XML coincida exactamente con case "nombre": en PHP (case-sensitive)
Modal no aparece
Causa: Nombre del modal mal configurado o no existe en XML
Solución: Verificar que setSettings('modalInsert', 'nombreModal') coincida con name="nombreModal" en XML
No se procesan múltiples registros
Causa: Método getArray('codes') no retorna datos
Solución: Verificar que en la vista XML los registros estén seleccionables y se envíen correctamente
🚀 Mejoras Recomendadas
Validación de Matrículas
protected function validarMatricula($matricula): bool
{
// Formato español: 1234ABC
return preg_match(\'/^\d{4}[A-Z]{3}$/\', $matricula);
}
protected function modalCoche()
{
$matricula = $this->request->request->get(\'matricula\');
if (!$this->validarMatricula($matricula)) {
Tools::log()->error(\'Formato de matrícula inválido\');
return;
}
// ... resto del código
}
Agregar validaciones específicas para datos de vehículos.
Acciones Asíncronas
protected function siniestro()
{
$codes = $this->request->request->getArray(\'codes\');
$total = count($codes);
$procesados = 0;
foreach ($codes as $code) {
// Procesar cada coche
$procesados++;
// Enviar progreso al cliente
$this->toolBox()->i18nLog()->info(
\'Procesando: \' . $procesados . \'/\' . $total
);
}
}
Para muchas operaciones, mostrar progreso al usuario.
Permisos Específicos
public function getPageData(): array
{
$page = parent::getPageData();
// ... configuración
// Restringir acceso según permisos
if (!$this->user->can(\'edit-coches\')) {
$page[\'show\'] = false;
}
return $page;
}
Agregar control de permisos para acciones críticas.
🧪 Demo: Flujo de Ejecución Completo
Usuario selecciona vehículos
En la lista, el usuario marca checkboxes de varios coches
Click en botón "Baja"
Usuario hace clic en botón rojo con icono de exclamación
Confirmación modal
Aparece modal pidiendo confirmación (confirm="true")
Ejecución siniestro()
Controlador obtiene IDs, valida, actualiza cada coche, guarda cambios
Feedback visual
Coches aparecen en rojo en la lista, log registra la acción
💡 Abre la consola del navegador para ver la simulación paso a paso