← Laravel: pedidos, dados e decisões de aplicação
03 / 10 · 65 MIN

Rotas, binding e middleware

Interpretar método, parâmetros, binding e middleware como contratos distintos do pedido. Localizar falhas antes do controller e evitar confundir a pertença de um recurso com o direito de o alterar.

Método, caminho e intenção

Uma URL não define sozinha uma ação. Uma rota POST para criar encomendas não deve ser convertida em any só porque um cliente enviou GET. Primeiro reconcilia a intenção da operação com o método e os controlos previstos.

O nome da rota serve a geração de URLs e deve ser único; não concede autorização nem altera os métodos aceites. Referências por nome permitem mudar o caminho sem manter cópias literais em várias vistas.

Restrições antes do controller

whereNumber limita o formato de um segmento. Num pedido com AB7, uma restrição numérica não converte o texto em zero: a rota não corresponde. Se nenhuma outra rota ou fallback corresponder, o tratamento normal devolve 404.

A validade sintática também não prova a existência do recurso. Na migração de IDs numéricos para códigos, revê tanto a restrição como a chave de pesquisa do modelo; aumentar o timeout SQL não ajuda se o controller nunca foi atingido.

Resolver modelos com nomes coerentes

No binding implícito, o parâmetro tipado do modelo deve corresponder ao nome do segmento. No exemplo, Ticket $ticket corresponde a {ticket}. Uma assinatura com string recebe uma intenção diferente; importar o modelo sem usar o tipo correto também não define o binding.

Quando não há modelo correspondente, o framework devolve 404 segundo o tratamento normal. Isto permite reconhecer uma falha de resolução anterior à ação sem a confundir com uma exceção SQL dentro do controller.

Pertença e permissão são decisões distintas

scopeBindings faz a resolução do filho através do pai, segundo as convenções da relação. Com Team::tickets e os segmentos do exemplo, um ticket de outra equipa não satisfaz a pesquisa. Mas um utilizador pode apontar a uma equipa existente à qual não tem acesso: o par pai-filho ser válido não o autoriza a ler ou alterar dados.

Por isso o exemplo mantém uma policy separada. Binding, autenticação e autorização respondem respetivamente por localização, identidade e operação permitida.

Middleware: entrada, retorno e âmbito

Imagina A envolvendo B e o handler H. Se ambos chamam $next uma vez, sem exceções ou interrupções, a entrada é A,B,H e o retorno é B,A. Um controlo colocado só depois de $next já pode encontrar a escrita realizada.

Também distingue atribuição global de atribuição a uma rota: withoutMiddleware pode excluir middleware de rota, mas não retira uma classe da pilha global. Confirmar a atribuição efetiva é mais útil do que mudar o método HTTP ou o nome da classe.

Dependências de ordem e grupos

Se CheckTenantAccess depende do contexto criado por ResolveTenant, documenta e configura a precedência necessária. Laravel permite definir prioridades no withMiddleware, incluindo acrescentar relações à lista existente. Não descartes sem análise a ordem dos componentes do framework.

No registo padrão instalado, routes/api.php recebe o grupo api e o prefixo /api; isso não aplica autenticação a todas as rotas. Uma rota pública e uma rota com auth:sanctum podem coexistir no mesmo ficheiro.

Definição publicada e definição carregada

A cache de rotas é um artefacto do router. Quando uma release mantém esse artefacto antigo, editar o ficheiro de rotas não demonstra que o processo esteja a usar a definição nova. Regenera a cache no processo de entrega e compara as rotas efetivas com o contrato esperado.

Distingue-a de config:cache, da cache de vistas e da cache do browser. No cenário de migração de IDs, uma correção no código ainda precisa de corresponder à versão carregada do router.

<?php
// Route excerpt: imports/application controller omitted.
Route::get('/teams/{team}/tickets/{ticket}', [TicketController::class, 'show'])
    ->whereNumber('team')
    ->whereNumber('ticket')
    ->scopeBindings()
    ->middleware('auth')
    ->name('teams.tickets.show');

// Controller signature excerpt; Team::tickets() is the matching relation.
public function show(Team $team, Ticket $ticket)
{
    // A separate policy check is required before disclosing this resource.
    Gate::authorize('view', $ticket);
    return view('tickets.show', ['ticket' => $ticket]);
}
NA PRÁTICA

O excerto é para interpretação de uma rota de leitura. Os dois segmentos são numéricos e os nomes correspondem aos modelos tipados. scopeBindings limita a pesquisa do ticket à relação tickets da equipa. auth identifica o utilizador; a policy view, definida pela aplicação, decide o acesso ao ticket.

Os imports, a relação, a policy e a vista não estão implementados neste excerto e não é pedida a sua execução.

Armadilhas comuns

Corrigir um método errado com any; tratar restrições numéricas como conversão de tipos; supor que scopeBindings executa policies; excluir middleware global com withoutMiddleware; alterar ficheiros e manter a cache de rotas antiga.

Tópicos relacionados: Ciclo do pedido e configuração · Validação e contratos dos pedidos · Autenticação, autorização e sessões

Leva esta ideia contigo

A rota define qual pedido pode chegar à ação. Binding resolve o recurso dentro de um âmbito; autorização decide o acesso. Middleware envolve a ação e pode interrompê-la. O diagnóstico deve mostrar qual contrato falhou e qual versão do router estava carregada.

Criar conta

Referência: HTTP methods and route matching · Laravel 13.x; PHP 8.3+