Laravel DI容器初始化时如何访问配置?config:cache执行失败问题
你在bootstrap/app.php中直接引入container.php执行服务绑定的时机不对——此时Laravel还未完成配置加载流程(配置加载是在应用bootstrap阶段的LoadConfiguration步骤中完成的),所以调用config()无法获取到配置值,返回null。而执行php artisan config:cache时,命令会先初始化应用实例,你的绑定代码提前执行,此时配置文件还没被读取,自然导致命令抛出异常失败。
之前用env()能正常工作,是因为env()直接读取环境变量,不需要经过Laravel的配置加载流程,但config:cache后env()会失效,所以你迁移到config()的方向是正确的,只是绑定时机需要调整。
将服务绑定代码从bootstrap/container.php迁移到Laravel的服务提供者中,利用框架的服务提供者机制,确保绑定代码在配置加载完成后执行。
步骤1:创建自定义服务提供者
新建App\Providers\ContainerServiceProvider.php,把原来container.php中的绑定逻辑移到这里:
<?php namespace App\Providers; use Illuminate\Support\ServiceProvider; use App\Services\Logger\LoggerContract; use App\Services\Logger\Logger; class ContainerServiceProvider extends ServiceProvider { public function register(): void { $this->app->singleton( LoggerContract::class, function ($app) { return new Logger( $app, config('logger'), ); } ); // 在这里添加其他所有原来在container.php中的服务绑定 } }
步骤2:注册服务提供者
在config/app.php的providers数组中添加这个服务提供者:
'providers' => [ // ... 其他默认服务提供者 App\Providers\ContainerServiceProvider::class, ],
步骤3:修改bootstrap/app.php
移除对container/container.php的引入:
<?php /** * @var \Illuminate\Foundation\Application $app */ $app = new Illuminate\Foundation\Application( realpath(__DIR__.'/../') ); // 移除这一行:require(__DIR__ . '/container/container.php'); return $app;
步骤4:执行缓存命令
现在运行php artisan config:cache,服务绑定会在配置加载完成后执行,config('logger')能正常获取到值,命令可顺利完成。
这种方式完全不影响原有测试流程:你依然可以通过config()->set('logger', [...])修改配置,或者在测试中替换服务实现,保持原有的优雅测试模式。
内容的提问来源于stack exchange,提问作者Kristi Jorgji

