Laravel está repleto de funcionalidades que, uma vez descobertas, deixam você impressionado e um pouco envergonhado por nunca ter conhecido antes. Uma dessas funcionalidades é o ContextualAttribute
. É uma ferramenta poderosa que ajuda você a escrever código mais limpo, mais expressivo e altamente sustentável, organizando como você resolve e injeta dependências.
Neste artigo, vamos falar um pouco sobre o que são atributos contextuais, por que eles são tão úteis e percorrer um exemplo prático do mundo real de como usá-los para simplificar um problema comum no desenvolvimento de APIs.
O que é um Atributo Contextual?
Em seu núcleo, um atributo contextual é um atributo especial do PHP 8 que permite que você tome controle de como o container de serviços resolve uma dependência para uma variável específica.
Pense em um método de controlador típico:
public function update(Request $request, string $id)
{
// ...
}
Quando você type-hint Request
, o container de serviços do Laravel sabe injetar a instância atual da requisição HTTP. Mas e se você precisar injetar algo mais específico, algo que requer lógica complexa para resolver? Por exemplo, injetar um modelo Workspace
que é determinado por uma chave de API enviada nos cabeçalhos da requisição, não nos parâmetros da URL. É aí que os atributos contextuais brilham.
Eles permitem que você anexe um atributo a um parâmetro, como #[CurrentWorkspace]
, e diga ao Laravel: "Ei, quando você vir este atributo em um parâmetro $workspace
(ou qualquer parâmetro), use minha lógica personalizada para resolvê-lo."
Atributos contextuais foram introduzidos no Laravel 11 e o Laravel já vem com vários embutidos como #[Storage]
, #[Auth]
, #[Cache]
, #[Config]
, #[DB]
, #[Log]
, e #[CurrentUser]
. Todos eles se conectam ao processo de resolução do container para injetar valores específicos com base no contexto da requisição.
Quando Você Deve Usar Atributos Contextuais?
Atributos contextuais não são para injeção de dependência cotidiana. Quero dizer, em alguns casos, um simples type-hint geralmente é suficiente (por exemplo, vinculação de modelo de rota). Eles se destacam em cenários onde a resolução da dependência não é direta e não pode ser tratada pelos mecanismos padrão do Laravel.
Aqui estão alguns casos de uso onde eles são um ajuste perfeito:
- Autenticação por Chave de API: Quando sua API determina o workspace/tenant a partir de uma chave de API em vez de parâmetros de URL - perfeito para serviços como Stripe, Paystack ou Flutterwave, onde o recurso está vinculado ao token de autenticação.
- Contexto Baseado em Cabeçalho: Resolvendo recursos de cabeçalhos personalizados, agentes de usuário ou outros metadados de requisição que não pertencem à URL.
- Padrões de Autorização Complexos: Quando você precisa resolver um recurso que requer múltiplas verificações de autorização ou lógica de negócios que vai além da simples vinculação de modelo de rota.
- Dependências Transversais: Injetando objetos que são necessários em múltiplos controladores, mas determinados por um estado de aplicação complexo em vez de parâmetros simples.
E muito mais.
Conclusão
Os atributos contextuais do Laravel fornecem uma maneira poderosa e elegante de lidar com cenários complexos de resolução de dependência que não podem ser resolvidos com a simples vinculação de modelo de rota. Eles são perfeitos para situações onde:
- Recursos são determinados por cabeçalhos, chaves de API ou outros dados não-URL
- Você precisa de lógica de autenticação e autorização complexa
- Você quer injeção de dependência type-safe em vez de puxar dados de objetos de requisição modificados
- Você tem preocupações transversais que afetam múltiplos controladores
Este padrão transforma código de autenticação repetitivo e propenso a erros em métodos de controlador limpos e declarativos. É uma técnica que escala lindamente conforme sua API cresce e adiciona requisitos de autenticação mais complexos.
Na próxima vez que você se encontrar copiando lógica de autenticação e resolução de recursos em múltiplos controladores de API, considere se um atributo contextual pode fornecer uma solução mais elegante.