必须先执行php artisan config:clear再运行config:cache,因FrankenPHP复用进程且优先加载bootstrap/cache/config.php,旧缓存会导致配置错误、密钥过期或环境误判,且config:cache依赖完整应用上下文,失败时需先清缓存再修复。

要重新生成,而且必须先清再生成,不能跳过 config:clear。
FrankenPHP 启动机制绕不开 config.php 缓存文件
FrankenPHP 是基于 SAPI 的 PHP 运行时,它不像传统 FPM 那样每次请求都完整重启 PHP 生命周期,而是复用进程和已加载的配置。Laravel 启动时仍会优先检查 bootstrap/cache/config.php 是否存在——只要它在,就会直接 require 这个文件,完全跳过 config/*.php 和 .env 解析流程。
- 如果你从 Nginx + PHP-FPM 迁移到 FrankenPHP 但没碰缓存,旧的
config.php仍被读取,看似“能跑”,实则可能沿用错误的驱动、过期的密钥或错位的环境判断 - FrankenPHP 对文件系统变化更敏感,某些版本甚至会在缓存文件 mtime 未更新时拒绝重载(尤其配合 OpCache 时)
- 迁移常伴随 PHP 版本升级或扩展变更(如移除 mcrypt、改用 sodium),旧缓存里序列化的值可能无法反序列化,导致
Unable to serialize closure或静默 fallback 到默认值
为什么不能只跑 config:cache?
config:cache 命令内部第一件事就是调用 config:clear,但它依赖当前环境能完整加载 Laravel 应用上下文——而 FrankenPHP 下的 Artisan 命令执行环境与 HTTP 请求环境不完全一致,尤其是 .env 加载时机和顺序可能不同。
- 如果
.env有语法错误(比如漏引号、换行符异常),config:cache会失败并卡在env()调用上,报错类似Undefined index: APP_NAME - 先手动运行
config:clear可确保缓存文件被物理删除,避免新命令因路径权限或文件锁问题写入失败 - 清完立刻试访问一个接口,若报配置缺失类错误(如
Class 'App\Providers\CustomConfigServiceProvider' not found),说明服务提供者注册阶段就出错了,此时再跑config:cache也无意义,得先修代码
FrankenPHP 部署脚本里必须加这两行
别信“反正缓存自动更新”这种说法。FrankenPHP 没有传统意义上的“部署后首次请求触发重建”的可靠机制,它更倾向复用已有状态。
立即学习“PHP免费学习笔记(深入)”;
- 部署流程中固定插入:
php artisan config:clear && php artisan config:cache - 如果用了多实例(比如 FrankenPHP 的 worker mode + static file server 分离),每个 worker 进程启动前都应确保
bootstrap/cache/config.php是最新且可读的——不能靠共享该文件,因为不同 worker 可能运行在不同 UID/GID 下 - CI/CD 中建议加校验:运行
php artisan tinker -n -c "echo config('app.name');",输出预期值才算通过;否则可能是缓存没生效,或APP_NAME被 fallback 到'Laravel'
最易被忽略的是:FrankenPHP 默认启用 OpCache,而 config.php 是 PHP 文件,OpCache 会缓存它的 opcode。哪怕你删了文件又重写,如果 OpCache 没刷新,PHP 还是执行旧字节码。所以生产环境务必确认 opcache.revalidate_freq=0 或至少设为 1,否则改完配置却看不到效果,排查方向全错。



















