Laravel8+PHP8.1执行config:cache遇循环引用及Closure问题求助
config:cache时循环引用与Closure配置冲突的解决方法 环境信息
- Laravel: 8
- PHP: 8.1
问题场景
执行php artisan config:cache时触发循环引用错误,且目标配置文件(config/adminer.php)中的permission项必须保留Closure回调——移除后会触发权限配置校验错误。
报错详情
ErrorException: var_export does not handle circular references
报错位置:vendor/laravel/framework/src/Illuminate/Foundation/Console/ConfigCacheCommand.php:63
相关代码片段:
59▕ 60▕ $configPath = $this->laravel->getCachedConfigPath(); 61▕ 62▕ $this->files->put( ➜ 63▕ $configPath, '<?php return '.var_export($config, true).';'.PHP_EOL 64▕ ); 65▕ 66▕ try { 67▕ require $configPath; +14 vendor frames 15 artisan:37 Illuminate\Foundation\Console\Kernel::handle()
已尝试的无效方案
- 通过
Handler.php捕获错误,无效果 - 移除
config/adminer.php中的Closure函数,触发新报错:"There are problems with your administrator.php config: The permission option must be a function"
解决方法
Laravel的config:cache命令依赖var_export序列化配置内容,但Closure和存在循环引用的对象无法被序列化。因此需要把Closure相关的配置逻辑从配置文件移到服务提供者中,动态注入:
生成自定义服务提供者
执行命令创建一个专门处理adminer配置的服务提供者:php artisan make:provider AdminerConfigServiceProvider在服务提供者中注入Closure逻辑
打开生成的AdminerConfigServiceProvider.php,在boot方法中动态设置permission配置,替换原配置文件中的Closure:<?php namespace App\Providers; use Illuminate\Support\ServiceProvider; class AdminerConfigServiceProvider extends ServiceProvider { public function boot() { // 这里写原config/adminer.php中permission对应的Closure逻辑 config()->set('adminer.permission', function () { return auth()->check() && auth()->user()->hasRole('admin'); }); } }修改原配置文件
在config/adminer.php中,把permission项改为占位符(比如null),避免缓存时触发序列化错误:// config/adminer.php return [ // 其他配置项 'permission' => null, // 由服务提供者动态赋值 ];注册服务提供者
在config/app.php的providers数组中添加自定义服务提供者:'providers' => [ // ... 其他服务提供者 App\Providers\AdminerConfigServiceProvider::class, ];重新执行缓存命令
现在可以正常执行配置缓存了:php artisan config:cache
原理说明
服务提供者的boot方法在框架启动阶段执行,此时配置缓存已经加载完成,动态设置的Closure不会被序列化到缓存文件中——既满足了adminer对权限函数的要求,又避开了var_export无法处理Closure和循环引用的问题。
内容的提问来源于stack exchange,提问作者Prathna Mehta

