Laravel Routing

Simplify Complex Actions with Single-Action Invokable Controllers

Punyapal Shah 1 min read
edit this tip
Use __invoke() in dedicated Single-Action Controllers to encapsulate complex domain operations into isolated, focused classes.

As controllers grow, large multi-action classes often accumulate disparate dependencies and private helper methods used by only one endpoint.

Single-action controllers implement PHP's magic __invoke() method, focusing on one specific responsibility.

Generating an Invokable Controller

Generate an invokable controller using Artisan:

php artisan make:controller GenerateInvoiceReportController --invokable

Controller Implementation

namespace App\Http\Controllers;

use App\Models\Invoice;
use Illuminate\Http\Request;
use Illuminate\Http\Response;

class GenerateInvoiceReportController extends Controller
{
    public function __invoke(Request $request): Response
    {
        $invoices = Invoice::whereBetween('created_at', [
            $request->date('start_date'),
            $request->date('end_date'),
        ])->get();

        return response()->view('reports.invoices', compact('invoices'));
    }
}

Clean Route Registration

When registering an invokable controller in your routes file, pass the class name directly without specifying a method:

use App\Http\Controllers\GenerateInvoiceReportController;
use Illuminate\Support\Facades\Route;

// Clean, single-class route mapping
Route::get('/reports/invoices', GenerateInvoiceReportController::class);

Summary

  • Encapsulates isolated, high-complexity operations (reports, checkouts, webhooks).
  • Keeps dependency injection minimal and focused on that single action.
  • Route definitions map cleanly to the class name without requiring method strings.
Tags: Laravel Routing Architecture Clean Code
Share on X

// Found an issue or want to contribute a tip? github.com/MrPunyapal/tips