laravel 6上下文绑定通过when()->needs()->give()在register()中配置,按请求类精准注入依赖实现,优先级高于全局绑定,支持多类数组和闭包动态解析。

Laravel 6 的服务容器支持上下文绑定(Contextual Binding),它让你能根据“谁在请求某个依赖”来决定注入哪个具体实现。这比全局绑定更精细,适合多场景共存的业务逻辑。
核心写法:when() → needs() → give()
必须在服务提供者的 register() 方法中配置,不能放在 boot() 里(此时容器已开始解析依赖,绑定会失效)。
当某个类被解析时,指定它需要的接口用哪个实现
比如订单处理器在不同上下文中要用不同的支付网关:
$this->app->when(OrderProcessor::class)
->needs(PaymentGateway::class)
->give(StripePaymentGateway::class);
这段代码的意思是:只要容器正在构建 OrderProcessor 实例,且该类构造函数或方法中声明了 PaymentGateway 类型提示,就自动注入 StripePaymentGateway。
多个类共享同一上下文规则
可用数组传入多个目标类:
$this->app->when([ShoppingCart::class, CheckoutController::class])
->needs(PaymentGateway::class)
->give(PayPalPaymentGateway::class);
这样,购物车和结算控制器用支付网关时,都走 PayPal 实现。
支持闭包动态决定实现
如果逻辑稍复杂(比如要读配置、判断环境),可以用 give() 接收闭包:
$this->app->when(ReportGenerator::class)
->needs(ExporterInterface::class)
->give(function ($app) {
return config('app.env') === 'local'
? new CsvExporter()
: new PdfExporter();
});
注意:闭包参数 $app 是容器实例,可安全调用 $app->make(),但避免在其中做耗时操作(如查数据库、读大文件),否则每次解析都会拖慢响应。
不能和普通绑定冲突
上下文绑定优先级高于全局 bind() 或 singleton()。但如果你先对 PaymentGateway::class 做了全局绑定,再加 when()->needs()->give(),上下文规则仍然生效——Laravel 会先匹配上下文,没命中才回落到全局绑定。
不复杂但容易忽略











