En el desarrollo con Laravel, tarde o temprano los controladores comienzan a crecer y a llenarse de lógica que no pertenece necesariamente allí. El Patrón Action (Action Pattern) ofrece una solución al dividir la lógica en clases que cumplen una única función: crear, actualizar, eliminar, procesar pagos, etc.
En esta guía, aprenderás:
Qué es el Patrón Action y sus ventajas
Cómo organizar tu código
Cómo inyectar tus acciones con el contenedor de Laravel
Cómo escribir tests para tus acciones
1. ¿Qué es el Patrón Action?
El Patrón Action promueve la creación de clases enfocadas en una sola responsabilidad. Cada clase se encarga de llevar a cabo una acción específica:
Crear un usuario
Actualizar un usuario
Eliminar un usuario
Generar reportes
Enviar correos
y más…
Ventajas
Responsabilidad Única: Código más legible y mantenible.
Reutilización: Fácil de usar la misma lógica en distintas partes de la aplicación.
Facilidad de Testeo: Clases más pequeñas y enfocadas en lo que deben hacer.
Escalabilidad: El crecimiento de la aplicación es más ordenado y modular.
2. Estructura de Carpetas
Por convención, podrías crear un directorio Actions dentro de app. Por ejemplo:
app
└── Actions
├── CreateUserAction.php
├── UpdateUserAction.php
└── DeleteUserAction.phpEste patrón no es una regla obligatoria, pero ayuda a mantener una estructura clara y ordenada.
3. Ejemplos de Acciones
3.1 CreateUserAction
La lógica para crear un usuario está contenida aquí. Se aprovecha la función __invoke() para que la clase sea invocable como si fuera un método.
3.2 UpdateUserAction
3.3 DeleteUserAction
4. Inyección de Dependencias con el Contenedor IoC
En lugar de instanciar manualmente las clases con new, utilizaremos el contenedor de Laravel para que se encargue de resolver nuestras acciones. Esto facilita la inyección de dependencias y promueve el desacoplamiento.
Ejemplo de Controlador: UserController
Nota:
De esta forma, no necesitas hacernew CreateUserAction()ni usarapp(CreateUserAction::class). Laravel inyectará automáticamente la acción apropiada, siempre y cuando hayas definido los tipos de parámetros en la función.
5. Tests con PHPUnit
A continuación, veremos cómo crear y ejecutar tests unitarios (para acciones) y tests de tipo feature (para el controlador).
5.1 Comandos para Crear Tests
Test de unidad:
php artisan make:test CreateUserActionTest --unitCrea un archivo en
tests/Unit/.Test de feature:
php artisan make:test UserControllerTestCrea un archivo en
tests/Feature/.
Tip: Laravel 11 ya trae PHPUnit integrado. No necesitas instalarlo aparte.
5.2 Test Unitario de una Acción
Imagina que acabamos de ejecutar:
php artisan make:test CreateUserActionTest --unitAhora tenemos tests/Unit/CreateUserActionTest.php. En él, puedes escribir:
Explicación:
RefreshDatabasereinicia la base de datos antes de cada test, asegurando un entorno limpio.app(CreateUserAction::class): Resolvemos la acción desde el contenedor.Afirmaciones: Comprobamos que la base de datos y los valores del usuario sean los esperados.
5.3 Test de Feature para el Controlador
Ahora creamos una prueba de tipo feature con:
php artisan make:test UserControllerTestEsto generará tests/Feature/UserControllerTest.php. En él, podemos escribir:
Explicación:
Feature Test: Se enfoca en probar el flujo completo de la aplicación (petición HTTP, respuesta, DB).
postJson: Enviamos una peticiónPOSTcon contenido JSON a la ruta/users.assertJson: Verificamos la estructura y contenido del JSON de respuesta.assertDatabaseHas: Revisamos que exista un registro específico en la tablausers.
Nota: Asegúrate de tener definidas las rutas para tus métodos en
routes/web.phporoutes/api.php. Un ejemplo sencillo podría ser:Route::post('/users', [UserController::class, 'store']);
6. Buenas Prácticas y Consejos
Responsabilidad Única
Asegúrate de que cada Action cumpla un propósito claro: “CreateUserAction”, “SendEmailAction”, etc.Refactoriza
Si tu Action crece demasiado, considera separarla en múltiples Actions.Inyección de Dependencias
Utiliza el contenedor de Laravel para resolver tus dependencias. Esto facilita las pruebas y el mantenimiento.Nombra adecuadamente
Usa nombres claros y significativos para tus tests y tus métodos de prueba.Rutinas de Limpieza
UtilizaRefreshDatabase(oDatabaseTransactions) para mantener tus pruebas aisladas y reproducibles.
Conclusión
El Patrón Action en Laravel te ayuda a mantener tus controladores livianos y ordenados, relegando la lógica de negocio a clases pequeñas y enfocadas. Al inyectar esas acciones mediante el contenedor IoC de Laravel, tu código se vuelve más desacoplado, propicio para la reutilización y el testeo.
Además, gracias a PHPUnit integrado, puedes cubrir tu aplicación con tests unitarios (para las acciones) y tests de tipo feature (para el controlador y la interacción con las rutas). Con estas prácticas, tu base de código se mantendrá escalable, segura y fácil de mantener a medida que tu proyecto crezca.
📚 ¿Quieres profundizar más?
He creado un libro completo sobre este tema: Acciones en Laravel, donde encontrarás ejemplos adicionales, casos de uso avanzados y mejores prácticas.
¡Ahora que tienes esta guía, estás listo para refactorizar tus controladores, escribir código más limpio y robusto, y cubrir tu aplicación con un set completo de pruebas!
¿Quieres seguir profundizando en las últimas novedades de Laravel?
No te pierdas nuestra ruta de Laravel 11, donde exploramos las funciones más recientes del framework, prácticas avanzadas y consejos para optimizar tus proyectos. ¡Te esperamos allí para que lleves tus aplicaciones al siguiente nivel!
Curso Laravel 12
Completo 2026
El único curso 100% actualizado que incluye Laravel 12, Livewire 3, Vue 3, React 19 e Inertia 2. Aprende con proyectos reales y las últimas funcionalidades.
star Incluido en cualquier suscripción