twig模板缓存必须显式设为cache: false并写死在dev配置中,且需开启auto_reload: true;ci应校验参数值与响应头,windows/docker环境须注意权限、时区和挂载问题。

twig.cache: false 必须写死在 config_dev.yml 里
很多人以为设了 APP_ENV=dev 就自动关缓存,其实 Twig 的 cache 配置项默认是路径字符串(如 "%kernel.cache_dir%/twig"),不是布尔开关。YAML 中的 ~ 或空值会被 Symfony 合并成默认路径,实际仍启用缓存。
正确做法是在 config/packages/twig.yaml 或 config/packages/dev/twig.yaml 中显式写:
twig:
cache: false
注意:false 是 YAML 字面量,不是字符串 "false"。设成 null、~、"" 都不生效。
若项目用了多个 Twig 环境(比如 email 渲染单独配了一个 email_twig),每个都要单独加 cache: false。
auto_reload: true 必须确认开启
即使 cache: false 生效,如果 auto_reload 关了,Twig 就不会监听文件修改时间,改完模板也不会重新加载——你会看到“改了没反应”的假象。
auto_reload 默认是 true,但以下情况可能被覆盖:
- 某些旧版 bundle 或自定义扩展在容器编译时重写了 twig.options
- Docker 容器挂载时宿主机和容器时区不一致,
filemtime()返回时间异常,导致 reload 判定失效 - IDE(如 PHPStorm)启用了“safe write”,先写临时文件再原子替换,Twig 监听不到变更事件
验证方式:删掉 var/cache/dev/twig/,改一个模板,刷新页面;如果目录里没新 PHP 文件生成,且页面内容实时更新,说明两者都生效了。
CI 流水线必须断言 cache 值为 false
本地配置再准,也防不住有人提交了错误的 config_prod.yml 覆盖、或 CI 构建时用了错误的环境变量。协作中真正可靠的,是让机器自己检查。
在 CI 脚本中加入两行验证:
运行 php bin/console debug:container --parameter=twig.options,grep 输出是否含 "cache":false(注意不是 null 或路径字符串)
用 curl -sI http://localhost/_profiler | grep -i "last-modified",必须有响应头——它代表 Twig 正在监听文件变更
这两项缺一不可。只查参数不保证 runtime 行为;只查 header 不保证配置没被运行时覆盖。
Windows 和 Docker 下容易被忽略的权限与路径问题
Windows 用户常遇到 file_put_contents(): Permission denied,原因往往是杀毒软件锁了 var/cache/dev/twig/,或目录本身不可写。不要只看报错位置,先检查该路径是否存在、是否可创建文件。
Docker 场景下更麻烦:
-
var/cache必须挂载为可写卷,且 UID/GID 匹配容器内 PHP 进程用户(常见坑:宿主机 root 写的文件,容器里 www-data 读不了) - 挂载方式用
bind mount而非named volume,否则文件时间戳可能不同步,auto_reload失效 - 确保宿主机和容器时区一致(
docker run -e TZ=Asia/Shanghai),否则filemtime()比较出错
最省事的调试方式:进容器执行 touch var/cache/dev/twig/test && ls -l var/cache/dev/twig/,确认能写、时间戳正常、无隐藏权限标志。











