# PHP框架项目配置不生效,我用命令定位原因
上线前觉得配置这东西不会出问题,一跑起来发现配置根本没生效,这坑踩了个正着。
前阵子帮同事排查一个问题:Laravel项目本地测试好好的,部署到服务器后某些配置死活不生效,代码里改了值,线上还是旧值。一开始以为是代码没更新到位,但git pull之后问题依旧。折腾了半天才发现是配置缓存的锅。
1 现象:改了配置但没效果
有个接口需要根据环境切换日志级别,本地配置的是debug,生产环境配置的是info。结果上线后发现生产日志全是debug级别的详细内容,既费磁盘又影响性能。
代码里读配置的逻辑很简单:
$level = config('logging.level', 'debug');
.env文件里确实配了LOG_LEVEL=info,但实际运行时拿到的永远是debug。
后来检查了config/logging.php,return的数组里直接写死了'level' => env('LOG_LEVEL', 'debug'),这个写法本身没问题,但问题出在别的地方。
2 初步排查:配置文件到底读没读
先确认配置文件有没有被加载。Laravel启动时会解析config目录下的php文件,如果这些文件被编译缓存了,后续的修改就不会生效。
可以用artisan命令看看当前的配置缓存状态:
php artisan config:cache
输出如下:
# 如果有缓存,会提示是否覆盖
Configuration cache created!
没有缓存的情况下会报没缓存。但关键不是这个命令,而是先要确认缓存文件在哪:
php artisan about | grep -i config
输出如下:
Configuration cache: /www/wwwroot/project/bootstrap/cache/config.php
这个bootstrap/cache/config.php文件就是罪魁祸首。php artisan config:cache会把所有config文件打包成这个php文件,之后.env的修改就不会再被读取了,除非清掉缓存。
3 确认缓存文件的存在和内容
直接看这个文件:
cat /www/wwwroot/project/bootstrap/cache/config.php | head -20
输出如下:
<?php return array(
'logging' =>
array (
'level' => 'debug',
),
...
);
果然,缓存文件里写死的是debug,根本没读到.env里的info。这文件是部署时自动生成的,可能是deploy脚本里有php artisan config:cache这条命令,或者前同事手动跑过。
再看文件修改时间:
stat bootstrap/cache/config.php | grep Modify
输出如下:
Modify: 2024-03-15 14:32:18.123456789 +0800
这个时间戳是部署时间,说明从那次部署之后配置就被锁死了。中间的.env修改全部白改。
4 手动验证:直接清缓存
如果确认是缓存问题,最直接的办法:
rm bootstrap/cache/config.php
php artisan config:clear
输出如下:
Configuration cache cleared!
再执行一次接口,日志级别立刻变成了info。
但这还没完。问题根源是为什么缓存会被生成?得找到触发配置缓存的那条命令。
5 排查触发源:是谁生成的缓存
用git blame看一下deploy脚本的历史:
git log --oneline --all -- deploy.sh | head -5
或者直接grep项目里谁调用了config:cache:
grep -r "config:cache" --include="*.sh" --include="*.php" --include="*.yml" .
输出如下:
deploy.sh:php artisan config:cache
deploy.sh:php artisan route:cache
找到元凶了。部署脚本里一次性缓存了config和route。开发者本地测试时不会跑这个脚本,所以本地没问题;服务器部署时跑了脚本,配置就被锁死了。
route缓存也是个坑,改了路由文件同样不会生效,但这个问题更隐蔽,因为不会报错,只会觉得某些路由"消失了"。
6 注意几个相关的坑
**第一个坑是bootstrap/cache目录权限**。如果这个目录没有写权限,config:cache会失败,但没有任何提示,只是命令执行完缓存文件没生成。这种情况更容易被忽视,因为看起来一切正常,但配置就是不生效。
**第二个坑是.env和config文件的加载顺序**。config文件里读取env用的是env()函数,这个函数只在配置加载时执行一次。配置被缓存之后,env()的调用结果也被写进了缓存文件,之后即使改了.env,config文件里的env()也不会再被调用。
**第三个坑是本地开发时的配置缓存**。有些IDE或者热更新工具会自动执行config:cache,本地改了配置但没刷新,也会导致同样的困惑。我遇到过PHPStorm的某些插件在保存文件时触发了一些清理操作。
7 结论和注意点
排查这类问题,用php artisan config:cache --no-interaction前先执行php artisan config:clear,这样能强制从源文件重新加载配置。
部署脚本里最好加上环境判断,生产环境才执行缓存操作,本地或测试环境跳过:
if [ "$APP_ENV" = "production" ]; then
php artisan config:cache
php artisan route:cache
fi
还有个更稳妥的做法:用git管理.env.example而不是真实的.env文件,部署时根据环境变量动态生成。这样即使缓存了,也能通过更新环境变量来调整配置。
**核心原则就一条:改配置之后,要么清缓存,要么不要缓存。**
如果你的项目也有类似的配置不生效问题,可以先检查bootstrap/cache/目录有没有config.php文件,有的话删掉试试。收藏备用,下次遇到同样的问题能省不少时间。