Construção explícita, resolução automática
Quando Laravel resolve um controller, pode construir dependências concretas cujo construtor também consegue satisfazer. Uma classe concreta sem dependências é o caso simples; não exige um binding manual só para existir. Isso não elimina a necessidade de pensar no grafo de construção.
Um parâmetro primitivo sem valor por omissão, uma interface sem implementação escolhida ou uma dependência em ciclo requerem atenção. Identifica o parâmetro que falhou antes de substituir todo o mecanismo por instanciações manuais.
Interfaces precisam de uma escolha
InvoiceSender descreve o contrato esperado pelo consumidor. A existência de HttpInvoiceSender e FakeInvoiceSender não estabelece uma preferência automática por nome ou ordem de ficheiro. O exemplo usa bind para declarar a implementação.
Laravel 13 também suporta atributos de binding; os exercícios que pressupõem ausência de binding excluem-nos explicitamente. Depois de a implementação ser escolhida, as suas próprias dependências ainda têm de ser resolvidas. A associação não confirma disponibilidade do serviço HTTP remoto.
Declarar e depois arrancar
No provider, register declara bindings no container. Não uses essa fase para consumir prematuramente serviços que outro provider ainda pode não ter registado. boot é chamado depois do registo dos providers e é o local apropriado para arranque como registar um view composer que depende desses serviços.
A ordem estabelece disponibilidade das declarações, não prova saúde das dependências externas. Um construtor ou boot que contacta um sistema remoto introduz uma dependência de arranque que deve ser assumida conscientemente.
Existir no disco não é estar inscrito
Um provider criado manualmente deve constar em bootstrap/providers.php no esqueleto usado neste percurso. O comando make:provider trata essa inscrição no fluxo documentado, mas copiar um ficheiro não garante o mesmo efeito. Se nenhum binding de um novo provider aparece, verifica primeiro o carregamento.
Um provider que apenas declara bindings pode ser diferido: implementa DeferrableProvider e identifica em provides os serviços que fornece. A lista é um contrato de resolução, não uma lista de rotas ou de utilizadores.
Identidade do objeto e duração
Singleton significa que resoluções posteriores reutilizam o mesmo objeto nesse container, salvo substituição ou descarte explícitos. Não significa um clone por chamada nem um objeto partilhado automaticamente entre processos PHP. Em workers duradouros, a duração pode ultrapassar um pedido ou job.
Se o objeto contém dados mutáveis de tenant, essa reutilização tem consequências diferentes das de um serviço sem estado. Define primeiro o contrato de isolamento e só depois escolhe a duração do binding.
Reutilização por ciclo e referências retidas
Scoped reutiliza uma instância dentro do ciclo de pedido ou job gerido pelo Laravel e limpa-a quando começa o ciclo seguinte, como em Octane ou num queue worker. O cenário assume que cada job resolve de novo o contexto. Não transforma o objeto numa fronteira de autorização e não apaga referências que código da aplicação tenha guardado noutro singleton.
Se uma referência antiga continua retida, mudar apenas o binding não demonstra isolamento. A revisão deve seguir tanto a resolução como a retenção.
Consumidores diferentes, valores diferentes
Um binding contextual permite selecionar uma implementação consoante a classe que está a ser construída. when identifica o consumidor, needs identifica a dependência e give fornece a implementação. Para o parâmetro string $endpoint de ReportClient, o exemplo usa giveConfig para obter a chave de configuração explícita.
Não se infere uma variável de .env a partir de qualquer nome de parâmetro. Compara este contrato com dois bindings globais sucessivos: estes não exprimem uma alternância nem a escolha por consumidor.
<?php
// Excerpt from a registered application provider.
public function register(): void
{
$this->app->bind(InvoiceSender::class, HttpInvoiceSender::class);
$this->app->scoped(TenantContext::class, fn () => new TenantContext());
$this->app->when(ReportClient::class)
->needs('$endpoint')
->giveConfig('services.reports.endpoint');
}
// Separate consumer excerpt; application classes/imports are omitted.
public function __construct(InvoiceSender $sender, TenantContext $context)
{
$this->sender = $sender;
$this->context = $context;
}O primeiro excerto pertence a um provider já inscrito; o segundo pertence a um consumidor resolvido pelo container. Os contratos e classes são nomes ilustrativos da aplicação, não programas descarregáveis. Prevê qual implementação é usada, que valor primitivo é necessário e quando o contexto deve ser substituído.
O exemplo não inclui autorização de tenant nem pretende fornecê-la através de scoped.
Armadilhas comuns
Esperar que o container escolha entre interfaces sem binding; resolver serviços de outro provider demasiado cedo; esquecer a inscrição manual; tratar singleton como memória global entre processos; usar scoped mas reter o objeto num singleton duradouro.
Tópicos relacionados: Ciclo do pedido e configuração · Filas, repetições e agendamento · Testes, cache e diagnóstico de releases
A resolução precisa de tipos, implementações e valores. Providers declaram bindings antes do arranque dependente desses serviços. A duração da instância faz parte do contrato: reutilização dentro de um pedido não deve implicar conservar contexto mutável no pedido seguinte.
Referência: Container automatic resolution · Laravel 13.x; PHP 8.3+