Laravel在Kernel构造函数中使用config助手函数报错问题
在Laravel Kernel构造函数中调用config助手函数报错的原因与解决方案
问题背景
你尝试根据不同环境加载对应的全局中间件,参考相关内容后在App/Http/Kernel.php的构造函数中使用config()助手获取当前环境,代码如下:
public function __construct(Application $app, Router $router) { parent::__construct($app, $router); // $env = 'devel' ; $env = config('app.env'); if ( $env == 'devel' ) { $this->prependMiddleware('\App\Http\Middleware\GlobalConfigDevel'); } }
但运行时抛出了异常:
Fatal error: Uncaught exception 'ReflectionException' with message 'Class config does not exist'
注释掉$env=config('app.env');后中间件能正常加载,而且在routes/web.php中调用config()助手却能正常返回环境参数:
Route::get('/', function () { return dd(config('app.env')); });
你想知道为什么构造函数里不能使用config()助手,同时已经找到临时解决办法:
$env = env('APP_ENV', 'devel');
原因分析
这本质上是Laravel应用启动顺序的问题:
- Kernel类的构造函数在应用容器尚未完全初始化完成时就会被调用。
config()助手函数的底层依赖容器中的config服务实例来获取配置,但此时这个服务还没有被绑定到容器中,所以直接调用config()会触发“类不存在”的反射异常。 - 而路由文件中的代码是在应用启动流程的后期执行的,此时容器已经完成了所有核心服务(包括配置服务)的绑定与初始化,所以
config()助手可以正常工作。
可行的解决方案
方案1:使用env()函数(你的临时办法)
直接通过env()函数读取环境变量是可行的,因为环境变量在应用启动初期就已经加载完毕:
$env = env('APP_ENV', 'devel');
⚠️ 注意:当你执行php artisan config:cache缓存配置后,env()函数在配置文件之外的地方会失效(Laravel会优先读取缓存的配置,不再解析.env文件)。所以如果你的项目会使用配置缓存,建议用下面的方案。
方案2:通过注入的Application实例获取配置
因为Kernel的构造函数已经注入了Application $app实例,你可以直接通过容器实例来获取配置服务,这样即使配置缓存后也能正常工作:
public function __construct(Application $app, Router $router) { parent::__construct($app, $router); $env = $app['config']->get('app.env'); // 也可以写成 $app->make('config')->get('app.env'); if ( $env == 'devel' ) { $this->prependMiddleware('\App\Http\Middleware\GlobalConfigDevel'); } }
这种方式绕过了助手函数,直接从容器中获取已初始化的配置服务,更可靠。
内容的提问来源于stack exchange,提问作者JLM
相关产品推荐
相关产品推荐

