Saltar al contenido

Los Single Action Controllers son una de las mejores prácticas en Laravel que transformarán la manera en que estructuras tu código. Si alguna vez has trabajado con controladores de cientos de líneas, sabes lo difícil que es mantenerlos. Hoy veremos cómo solucionarlo.

Son controladores con un único método __invoke() que se ejecuta automáticamente cuando se llama a la clase. Representan una sola acción o responsabilidad en lugar de agrupar múltiples funcionalidades relacionadas.

<?php

class ProcessPaymentController extends Controller
{
    public function __invoke(PaymentRequest $request)
    {
        // Single responsibility: process payment
        $payment = $this->paymentService->process($request->validated());
        
        return redirect()->route('payment.success')
            ->with('message', 'Payment processed successfully');
    }
}

El Problema: Controllers Monolíticos

Los controladores tradicionales tienden a crecer descontroladamente:

  • Clases enormes con decenas de métodos vagamente relacionados

  • Difícil navegación entre cientos de líneas de código

  • Testing complejo que requiere cargar dependencias innecesarias

  • Alto acoplamiento que dificulta los cambios

Ventajas de Single Action Controllers

1. Responsabilidad Única (SRP)

Cada controlador se centra en una sola tarea bien definida, cumpliendo completamente con el Single Responsibility Principle.

2. Testing Simplificado

Tests más enfocados, con menor configuración y mejor cobertura de código.

3. Mejor Organización

Estructura autodocumentada y navegable que comunica claramente la intención de cada acción.

4. Bajo Acoplamiento

Menor dependencia entre componentes, facilitando cambios y refactoring.

¿Cuándo Usar Single Action Controllers?

Casos ideales:

  • Procesos complejos con múltiples pasos

  • Operaciones específicas con requisitos particulares

  • Workflows con reglas de negocio encapsuladas

  • Acciones fuera del CRUD estándar

  • Cuando la legibilidad es prioritaria

Ejemplos perfectos:

  • Exportación de datos (Excel, PDF)

  • Envío de correos específicos

  • Procesamiento de archivos

  • Transacciones financieras

  • Integraciones con APIs externas

  • Cambios de estado complejos

Comparativa: Tradicional vs Single Action

Enfoque tradicional:

<?php

class PaymentController extends Controller
{
    public function process(Request $request) { /* ... */ }
    public function refund(Request $request) { /* ... */ }
    public function history() { /* ... */ }
    public function export() { /* ... */ }
}

Con Single Action Controllers:

<?php

// app/Http/Controllers/Payments/ProcessPaymentController.php
class ProcessPaymentController extends Controller
{
    public function __invoke(PaymentRequest $request) { /* ... */ }
}

// app/Http/Controllers/Payments/RefundPaymentController.php
class RefundPaymentController extends Controller
{
    public function __invoke(RefundRequest $request) { /* ... */ }
}

Estructura de Carpetas Recomendada

app/Http/Controllers/
├── Dashboard/
│   └── ShowDashboardController.php
├── Payments/
│   ├── ProcessPaymentController.php
│   └── RefundPaymentController.php
├── Reports/
│   ├── GenerateMonthlyReportController.php
│   └── ExportAnnualReportController.php
└── Users/
    └── ExportUsersController.php

Configuración de Rutas

Laravel hace muy simple trabajar con Single Action Controllers:

<?php

use App\Http\Controllers\Payments\ProcessPaymentController;

// Direct class reference
Route::post('/payments/process', ProcessPaymentController::class)
    ->name('payments.process');

// Using action() helper for URLs
$url = action(ProcessPaymentController::class);

¿Cuándo NO Usar Single Action Controllers?

Mantén controllers tradicionales para:

  • CRUD básicos: Un UserController estándar para operaciones REST simples

  • APIs con endpoints relacionados: Cuando múltiples endpoints comparten lógica

  • Operaciones estrechamente vinculadas: Como AuthController con login/logout/register

Testing Mejorado

<?php

class ProcessPaymentControllerTest extends TestCase
{
    public function test_payment_processes_successfully()
    {
        $response = $this->post(action(ProcessPaymentController::class), [
            'amount' => 100,
            'currency' => 'EUR'
        ]);
        
        $response->assertOk();
    }
}

Arquitectura Comparada

Aspecto

Fat Controllers

Slim Controllers

Single Action

Testing

Difícil

Mejorado

Simple

Mantenibilidad

Baja

Media

Excelente

Acoplamiento

Alto

Medio

Bajo

SRP

No cumple

Parcial

Total

Migración Incremental

No necesitas refactorizar todo de golpe. Empieza por:

  1. Identificar los controllers más grandes

  2. Extraer las acciones más complejas

  3. Crear Single Action Controllers para nuevas features

  4. Refactorizar gradualmente el código legacy

Conclusión

Los Single Action Controllers no son una bala de plata, pero ofrecen beneficios claros:

  • Código más organizado y autodocumentado

  • Mejor colaboración con menos conflictos en Git

  • Testing simplificado con mejor cobertura

  • Arquitectura escalable que crece sanamente

La clave está en identificar cuándo una acción merece su propio controlador. Si un método tiene lógica compleja, dependencias específicas o representa un caso de uso único del negocio, probablemente sea candidato para un Single Action Controller.


school Curso completo

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.

access_time 8 horas de contenido
layers 4 tecnologías en 1
update 100% actualizado
code Proyectos prácticos
Ver Curso Laravel 12 arrow_forward

star Incluido en cualquier suscripción

Rutas de aprendizaje