Capítulo 04: Middlewares Globais e de Rota, Tratamento de Exceções
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.