Generar catálogos (make:catalog)¶
El comando php artisan make:catalog
crea un módulo de catálogo completo, listo para usar, siguiendo los patrones del boilerplate:
- Backend: migración, modelo, repository + interface, service + interface, requests (Index/Store/Update), policy, controller, permisos.
- Frontend (Inertia + React): páginas
index
,form
,show
,columns
,filters
bajoresources/js/pages/
(en minúsculas), con DataTable, filtros, acciones en bloque y exportación (CSV/XLSX/JSON). - Infraestructura: rutas (en
routes/catalogs.php
), entrada de menú (enresources/js/menu/generated.ts
), y bindings enDomainServiceProvider
.
El resultado es un módulo consistente, con permisos y policies correctamente cableados, UI coherente con Roles/Usuarios y exportación lista.
Tip: puedes ejecutar en modo "dry run" para ver el plan sin escribir archivos.
Requisitos previos¶
bootstrap/providers.php
debe registrarApp\Providers\AuthServiceProvider::class
para que las Policies carguen. Si falta, las policies no se registran yGate
devolverá 403 aunque el usuario tenga permisos.- Asegúrate de tener
DomainServiceProvider
habilitado (viene incluido por defecto en el boilerplate) y queconfig/permissions.php
agregue los permisos deconfig/permissions/*.php
. - Las páginas Inertia deben estar en
resources/js/pages/
con rutas en minúsculas (p. ej.resources/js/pages/catalogs/tipo-documento/index.tsx
).
Uso básico¶
php artisan make:catalog TipoDocumento \
--fields="code:string:50:unique,name:string:120,active:boolean,sort_order:int:nullable" \
--menu="Catálogos"
Opciones disponibles:
Name
(argumento): Nombre del modelo en StudlyCase. Ej.:TipoDocumento
.--fields
: Lista separada por comas:nombre:tipo:args:flags
. Ej.:code:string:50:unique
.--menu
: Etiqueta del grupo en el sidebar para insertar la entrada.--soft-deletes
: Agregadeleted_at
y adapta unique awithoutTrashed()
en reglas.--uuid-route
: Usauuid
como route key y lo agrega al modelo y requests.--force
: Sobrescribe archivos existentes del módulo.--dry-run
: Muestra un resumen (archivos a crear/modificar) sin escribir.
Sintaxis de --fields¶
- Tipos soportados:
string
/varchar
,int
/integer
,bigint
,decimal(precision,scale)
,boolean
/bool
,text
,enum(A,B,C)
(mapeado comostring(50)
en BD). - Flags:
nullable
,unique
. - Normalizaciones automáticas:
active
→is_active
,order
→sort_order
.
Ejemplos:
code:string:50:unique,name:string:120,active:boolean,sort_order:int:nullable
name:string:100,description:text:nullable
estado:enum(ACTIVO,INACTIVO)
precio:decimal:12,2:nullable
Archivos generados y modificados¶
Se crean:
database/migrations/*_create_{tabla}_table.php
app/Models/{Model}.php
app/Contracts/Repositories/{Model}RepositoryInterface.php
app/Repositories/{Model}Repository.php
app/Contracts/Services/{Model}ServiceInterface.php
app/Services/{Model}Service.php
app/Http/Requests/{Model}IndexRequest.php
app/Http/Requests/{Model}StoreRequest.php
app/Http/Requests/{Model}UpdateRequest.php
app/Policies/{Model}Policy.php
app/Http/Controllers/{Model}Controller.php
config/permissions/{snake}.php
resources/js/pages/catalogs/{slug}/index.tsx
resources/js/pages/catalogs/{slug}/columns.tsx
resources/js/pages/catalogs/{slug}/filters.tsx
resources/js/pages/catalogs/{slug}/form.tsx
resources/js/pages/catalogs/{slug}/show.tsx
Se modifican idempotentemente (entre marcadores):
routes/catalogs.php
(grupo de rutas con middleware de permisos por operación)resources/js/menu/generated.ts
(entrada del menú con permiso.view
)app/Providers/DomainServiceProvider.php
(bindings repo y service)app/Providers/AuthServiceProvider.php
(mapeoModel => Policy
), para evitar 403 enauthorize()
Nota: las inserciones son idempotentes. Si eliminas manualmente líneas dentro de los marcadores, puedes re-ejecutar el comando para reinsertarlas.
Convenciones de permisos y policies¶
- Se crea
config/permissions/{snake}.php
con permisos estándares:.view
,.create
,.update
,.delete
,.restore
,.forceDelete
,.export
,.setActive
bajo el prefijocatalogs.{slug}
. - La
Policy
extiendeBaseResourcePolicy
conabilityPrefix = 'catalogs.{slug}'
. - El middleware de rutas y la UI (botones/acciones) usan esos permisos.
Frontend (Inertia + React)¶
- Páginas bajo
resources/js/pages/catalogs/{slug}/
con layout y espaciados alineados a Roles. - DataTable con filtros, ordenamiento, selección, acciones masivas y export.
- Botón “Nuevo”, acciones “Editar/Eliminar/Activar” condicionadas por
auth.can[...]
compartido enHandleInertiaRequests
.
Beneficios¶
- Consistencia total con módulos base (Roles/Usuarios): permisos, policies, requests y rutas.
- Previene 403 habituales: registra automáticamente la
Policy
enAuthServiceProvider
. - Productividad: un comando crea BE + FE + permisos + routing + menú.
- Idempotencia: inserciones en archivos existentes entre marcadores.
- Export con cabeceras amigables en español y layout moderno, listo para producción.
Ejemplos¶
# Catálogo con campos típicos y menú "Catálogos"
php artisan make:catalog TipoDocumento \
--fields="code:string:50:unique,name:string:120,active:boolean,sort_order:int:nullable" \
--menu="Catálogos"
# Con UUID en rutas y soft deletes
php artisan make:catalog Producto \
--fields="sku:string:20:unique,nombre:string:120,precio:decimal:12,2:nullable,activo:boolean" \
--uuid-route \
--soft-deletes \
--menu="Catálogos"
Solución de problemas¶
- 403 al editar/actualizar:
- Verifica que
App\Providers\AuthServiceProvider
esté enbootstrap/providers.php
. - Confirma que el usuario tiene
catalogs.{slug}.update
. - Si limpiaste rutas o menú, vuelve a ejecutar el generador con
--force
.
- Verifica que
- No aparece en el menú:
- Revisa
resources/js/menu/generated.ts
y los marcadores. El generador reinsertará si están presentes.
- Revisa
- Rutas faltantes:
- Asegúrate de mantener los marcadores en
routes/catalogs.php
.
- Asegúrate de mantener los marcadores en
- Export falla:
- Asegúrate de tener configurados los Exporters (
exporter.csv
,exporter.xlsx
,exporter.json
) enDomainServiceProvider
(ya vienen).
- Asegúrate de tener configurados los Exporters (
Flujo recomendado post-generación¶
- Ejecuta migraciones y seeders:
php artisan migrate php artisan db:seed
- Inicia el server y prueba en
/catalogs/{slug}
. - Ajusta columnas/validaciones en los archivos generados si es necesario.
Con este generador, crear catálogos alineados al boilerplate es cuestión de segundos, manteniendo calidad, consistencia y seguridad.