Laravel 6 闭包绑定中,容器自动将 $app 实例作为第一个参数注入闭包,无需 use 或手动传递;必须声明参数(如 function($app)),方可安全调用 $app->make()、config() 等方法解析依赖或读取配置。

Laravel 6 的服务容器在闭包绑定中,容器实例会自动作为第一个参数传入闭包,你只需在闭包签名中声明 $app(或任意变量名),就能直接使用它来解析其他依赖、读取配置、获取环境变量等。
不需要手动“传递”容器——它是 Laravel 容器机制内置的行为。
✅ 正确写法:闭包自动接收 $app
$this->app->bind(EmailService::class, function ($app) {
// $app 就是当前服务容器实例,可安全调用 make()、config()、environment() 等
$apiKey = $app->make('config')->get('services.sendgrid.api_key');
return new SendGridEmail($apiKey);
});关键点:
- 闭包必须接受一个参数(通常叫
$app),否则无法访问容器; - 不要写
use ($app)—— 容器不是从外部作用域use进来的,而是由 Laravel 内部调用时注入的; - 在闭包里调用
$app->make()是安全且推荐的,用于解析子依赖(比如HttpClient、config、logger); - 避免在闭包里做耗时操作(如读大文件、远程请求),因为每次
make()都会执行该闭包(bind模式下)。
⚠️ 常见错误写法
// ❌ 错误:没声明参数,$app 不可用
$this->app->bind(Logger::class, function () {
return new Logger('app'); // 无法访问容器,拿不到 config 或其他服务
});
// ❌ 错误:试图 use 外部 $app(此时 $app 可能未初始化或不可用)
$app = $this->app;
$this->app->bind(Logger::class, function () use ($app) { ... });
// ❌ 错误:手动 new 类却忽略依赖注入(破坏了容器解耦能力)
$this->app->bind(HttpClient::class, function () {
return new GuzzleHttp\Client(); // 没有通过 $app->make() 解析其内部依赖(如 handler stack)
});? 小技巧:闭包里还能做什么?
- 获取配置:
$app->make('config')->get('database.default') - 解析其他绑定:
$app->make(CacheContract::class) - 判断环境:
$app->environment('local') - 访问请求上下文(仅在 request 生命周期内可靠):
$app->make('request')
注意:若在
register()中绑定,此时请求对象可能尚未创建,慎用request或session等运行时服务。
? 补充:singleton() 闭包也一样接收 $app
$this->app->singleton(DatabaseConnection::class, function ($app) {
return new DatabaseConnection(
$app->make('config')->get('database.connections.mysql')
);
});逻辑与 bind() 完全一致,区别只在于是否缓存实例。
本质上,Laravel 的闭包绑定就是“带容器上下文的工厂函数”,你只要签对参数,就能稳稳用上整个容器生态。


















