Especialização em Backend com PHP & Laravel • Laravel 11 & PHP 8.3+ • Eloquent ORM, Sanctum, Filas, Horizon e APIs Corporativas


🗺️ Mapa Conceitual do Tópico

flowchart TD
    A["Requisição HTTP"] --> B["Middleware 1: handle($request, $next)"]
    B --> C["Middleware 2 (ex: auth:sanctum)"]
    C --> D["Controller"]
    D --> E["Resposta gerada"]
    E --> F["Middleware 2 (pós-processamento)"]
    F --> G["Middleware 1 (pós-processamento)"]
    G --> H["Resposta final ao Cliente"]
    D -.exceção.-> I["bootstrap/app.php: withExceptions()"]
    I --> H

    style A fill:#e1f5fe,stroke:#03a9f4,stroke-width:2px
    style D fill:#ede7f6,stroke:#7e57c2,stroke-width:2px
    style I fill:#ffebee,stroke:#e53935,stroke-width:2px
    style H fill:#e8f5e9,stroke:#4caf50,stroke-width:2px

🏛️ 1. O Pipeline de Middlewares

Um middleware do Laravel implementa o padrão Pipeline: ele recebe a requisição, pode agir antes de repassá-la adiante com $next($request), e pode agir depois, sobre a resposta que retorna dessa chamada. Isso os torna ideais para cross-cutting concerns (autenticação, logging, headers) sem poluir cada controller:

<?php
namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class CheckApiVersion
{
    public function handle(Request $request, Closure $next): Response
    {
        $response = $next($request); // tudo depois desta linha roda no "caminho de volta"
        $response->headers->set('X-Api-Version', '1.0');
        return $response;
    }
}

Se o middleware retornar uma resposta sem chamar $next($request), o pipeline é interrompido ali — é assim que um middleware de autenticação bloqueia requisições não autorizadas antes de qualquer controller ser executado.


⚙️ 2. Registro no Laravel 11: bootstrap/app.php

A partir do Laravel 11, a estrutura de kernel HTTP/console foi eliminada: não existem mais app/Http/Kernel.php nem app/Exceptions/Handler.php. Tudo é centralizado de forma funcional em bootstrap/app.php:

<?php
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Middleware;

return Application::configure(basePath: dirname(__DIR__))
    ->withMiddleware(function (Middleware $middleware) {
        $middleware->append(\App\Http\Middleware\CheckApiVersion::class);
        $middleware->alias(['api.version' => \App\Http\Middleware\CheckApiVersion::class]);
    })->create();

O método alias() permite referenciar o middleware por um nome curto direto nas rotas (Route::get(...)->middleware('api.version')), evitando escrever o FQCN completo repetidamente.


🚨 3. Tratamento Global de Exceções

Também centralizado em bootstrap/app.php, o bloco withExceptions() permite interceptar tipos específicos de exceção e customizar a resposta — essencial em uma API para nunca vazar uma página HTML de erro 500 do Laravel para um cliente que espera JSON:

<?php
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Database\Eloquent\ModelNotFoundException;

->withExceptions(function (Exceptions $exceptions) {
    $exceptions->render(function (ModelNotFoundException $e) {
        return response()->json(['erro' => 'Recurso não encontrado'], 404);
    });
})

Cada render() adicional é avaliado na ordem declarada até encontrar um handler compatível com o tipo da exceção lançada — permitindo tratar ValidationException, AuthorizationException e exceções de domínio customizadas de forma independente, todas convergindo para respostas JSON consistentes.