Twig 缓存需显式配置 cache: false 并验证 auto_reload: true 生效,因 debug=true 不影响 Twig 缓存机制;需检查缓存目录是否为空、响应头含 Last-Modified,且 CI 断言配置正确。

改了 Twig 模板却没变化,不是浏览器缓存,也不是没保存,而是 Twig 缓存没真正关掉——cache: false 必须显式写死在配置里,且要验证 auto_reload: true 生效。
为什么 debug=true 不能代替 cache: false
Twig 的缓存开关和 Symfony 的 debug 模式完全独立。debug 控制 Profiler、错误堆栈、容器热加载等,但 Twig 默认仍会把 .twig 编译成 PHP 文件并缓存在 var/cache/dev/twig/ 下。即使你改了模板、刷新页面,只要缓存文件还存在且未被标记为过期,Twig 就直接执行它,跳过解析。
-
debug: true只保证auto_reload: true默认开启,但 reload 依赖缓存是否启用;如果cache指向一个真实可写目录(比如默认的%kernel.cache_dir%/twig),reload 就不会触发重新编译 - Windows 下杀毒软件或 IDE 的“safe write”可能让文件变更时间(
filemtime())不更新,导致 reload 判定“没变”,从而跳过重载 - 用
php bin/console server:run启动时若漏掉--env=dev,实际运行在 prod 环境,cache: true是硬编码行为,debug 设置完全无效
怎么正确设置 cache: false
必须在 Twig 配置中明确把 cache 设为 YAML 的布尔字面量 false,而不是空值、~、字符串 "false" 或注释掉。
- 在
config/packages/twig.yaml中写:twig: cache: false auto_reload: true
- 不要用
cache: "%kernel.cache_dir%/twig"—— 这个路径在cache:warmup后会被创建,实际启用磁盘缓存 - 如果项目用了多个 Twig 实例(如 email 渲染单独配了
email_twig),每个都要单独设cache: false - 设成
null或~会被 Symfony 合并为默认路径,等同于没关
如何验证缓存真关掉了
不能只看页面是否变,得看缓存目录和响应头是否符合预期。
- 删掉
var/cache/dev/twig/目录,改一个模板并保存,刷新页面后检查该目录是否仍为空 —— 若有新.php文件生成,说明cache没生效 - 访问任意含 Twig 渲染的页面(比如
/_profiler),用curl -I http://localhost/_profiler | grep Last-Modified查响应头:必须出现Last-Modified,否则auto_reload未工作或缓存未关闭 - CI 脚本中加断言:
php bin/console debug:container --parameter=twig.options | grep '"cache":.*false',防止某人本地改了配置却没提交
容易被忽略的协作陷阱
最麻烦的不是技术关不掉,而是不同人机器上缓存状态不一致:A 改了 base.html.twig,B 刷新看到旧内容,两人互相怀疑代码没提交或没拉取。
- Docker 环境下,
var/cache必须挂为可写卷,且宿主机与容器时区一致,否则filemtime()返回时间偏差,reload 判定失效 - 某些 IDE(如 PHPStorm)默认开启“safe write”,保存时先写临时文件再原子替换,Twig 监听的是原文件 inode,变更不被感知 —— 需手动关掉该选项
- 团队里有人执行过
cache:clear却忘了加--env=dev,清掉了 dev 缓存目录,Twig 回退到内存ArrayCache,表现像“部分生效”,极难排查
真正起作用的从来不是“怎么关”,而是“怎么确保所有人同一时刻都关着”。把 cache: false 写死在版本库配置里,CI 加一条 grep 断言,比每次问“你清缓存了吗”可靠得多。


















