frankenphp 重启后 symfony 容器缓存不刷新,因其热更新仅重载 php 进程和路由,不自动清理或重建 var/cache/prod/container* 编译文件;需在 reload 前显式执行 cache:clear --env=prod 和 cache:warmup --env=prod,并确保 app_debug=0、app_env=prod 生效,同时调用 opcache_reset() 避免 opcache 持久化旧类。

为什么 FrankenPHP 重启后 Symfony 容器缓存不刷新?
因为 Symfony 的容器缓存(var/cache/prod/Container*)是编译后的 PHP 类文件,FrankenPHP 热更新只重载 PHP 进程和路由配置,但不会自动删除或重建这些缓存文件——它根本不知道它们该被清掉。
典型现象是:改了服务定义、加了新参数、甚至删了某个 services.yaml 配置,FrankenPHP 重启后请求仍走旧逻辑,php bin/console debug:container 显示的也是旧服务列表。
- FrankenPHP 的热更新机制基于信号(如
SIGHUP),仅触发 PHP-FPM-style 的 worker 重载,不执行 Symfony 的缓存清理流程 - 容器缓存文件有硬编码哈希名(如
ContainerD1a2b3c),Symfony 运行时靠var/cache/prod/appDevDebugProjectContainer.php这类入口文件定位,而该入口文件不会随热更新自动更新 - 如果用
APP_ENV=prod且未预热,首次请求会动态生成缓存,但 FrankenPHP 不保证该请求触发在所有 worker 中同步完成,导致部分 worker 加载旧缓存
如何让 FrankenPHP 热更新真正生效?
必须显式介入缓存生命周期,不能依赖 FrankenPHP 自动处理。最可靠的方式是在热更新前强制重建容器缓存。
- 在 FrankenPHP 的 reload 脚本或 systemd 服务中,把
php bin/console cache:clear --env=prod和php bin/console cache:warmup --env=prod作为 reload 前置步骤 - 避免只用
cache:clear:它只删文件,不重建;warmup 才真正触发容器编译,生成新的Container*目录和入口文件 - 确保
APP_DEBUG=0且APP_ENV=prod已在环境变量中生效,否则 warmup 会降级为开发模式缓存,带调试代理开销 - 如果使用多 worker 实例(如
frankenphp_workers = 4),warmup 必须在所有 worker 启动前完成,否则首个请求可能由某个 worker 触发竞态缓存生成
能否跳过 warmup,靠首次请求自动生成?
能,但不推荐用于生产热更新场景——风险在于缓存生成过程中的性能毛刺和状态不一致。
- 首次请求生成缓存会触发完整 DI 编译,耗时明显(尤其服务多时),用户会感知到卡顿或超时
- 多个并发请求可能同时尝试生成缓存,造成重复写入或文件锁冲突,
var/cache/prod/下可能出现残留临时文件或损坏的Container*目录 - FrankenPHP 的 worker 是独立进程,A worker 生成的缓存对 B worker 不可见,直到其下次加载入口文件——而入口文件本身也可能被缓存(OPcache)
- 若启用了 OPcache 文件缓存(
opcache.file_cache),旧容器类可能被持久化,即使删了var/cache,worker 仍可能加载磁盘缓存里的旧类
检查缓存是否真被更新的三个关键点
别只看 var/cache/prod/ 目录时间戳,要验证运行时实际加载的是哪个容器。
- 查当前加载的容器类名:
php bin/console debug:container --env=prod | head -n 5,对比输出中的 “Container” 后缀哈希是否与var/cache/prod/下最新目录名一致 - 检查入口文件内容:
cat var/cache/prod/appProdProjectContainer.php | grep "class Container",确认类名和文件路径匹配 - 观察日志:启用
kernel.debug=false时,容器编译成功不会打日志;但若看到"Compiling container"或"Writing cache file",说明 warmup 正在执行——而热更新后没看到,大概率没跑成
最易被忽略的是 OPcache 对容器类的二次缓存。FrankenPHP 默认启用 OPcache,且 opcache.validate_timestamps=0 在生产常见,这意味着即使你替换了容器 PHP 文件,OPcache 仍可能返回旧字节码。务必在 warmup 后执行 opcache_reset() 或设置 opcache.validate_timestamps=1(仅限调试)。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











