Symfony Twig模板缓存默认开启且深度绑定环境,需协同调整缓存路径、编译策略和APP_ENV/debug环境变量;生产环境强制启用,开发环境设cache: false仅在debug=true时生效,且需手动清理var/cache/*/twig或使用twig:cache:clear命令。

模板缓存不是关掉就完事——Symfony 3 的 Twig 模板缓存默认开启且深度绑定环境,直接删 var/cache 或改配置不生效是常态;真正要动的是缓存路径、编译策略和环境变量三者协同。
Twig 缓存目录被硬编码进 dev/prod 环境判断
Twig 缓存位置不由你手动指定,而是由 kernel.debug 和 kernel.environment 联合决定。即使你在 config/packages/twig.yaml 里写了 cache: false,只要 APP_ENV=dev 且 debug=true,Twig 仍会把模板编译到 var/cache/dev/twig/ 并复用——它只是“不校验源文件改动”,不是“不缓存”。
- 验证当前缓存路径:执行
php bin/console debug:container --env=dev | grep twig,找twig.cache_warmer或twig.template_cache_extension相关输出 - 强制禁用编译缓存(仅限开发调试):在
config/packages/twig.yaml中设cache: '%kernel.cache_dir%/twig'→ 改成cache: false,但必须配合APP_DEBUG=true才有效 - 若用了
APP_ENV=prod,cache: false会被忽略——生产环境强制启用缓存,这是 Symfony 3 的硬限制
修改模板后不刷新?先查 Twig 编译时间戳是否被跳过
Symfony 3 默认用 filemtime() 判断模板是否变更,但某些 NFS、Docker volume 或 Windows 文件系统会缓存 mtime,导致 Twig 认为“没改过”,继续返回旧编译结果。
- 临时绕过时间戳检查:在
config/packages/twig.yaml加上auto_reload: true(开发环境默认已开,但确认下没被覆盖) - 更彻底的方案:把
cache: '%kernel.cache_dir%/twig'改成指向一个每次启动都重建的临时目录,例如cache: '/tmp/twig_cache_'.uniqid()(需在 PHP 配置中动态生成) - 注意:若模板里用了
{% include %}或{% extends %},父模板和子模板的 mtime 都要变,只改一个文件可能无效
清除 Twig 缓存不能只靠 cache:clear
php bin/console cache:clear 默认只清 Symfony 容器、路由、事件监听器等缓存,Twig 编译文件在 var/cache/{env}/twig/ 下是独立目录,不会被自动删除——尤其当 APP_ENV=prod 时,cache:clear 甚至会跳过 Twig 清理逻辑。
- 手动删 Twig 缓存目录:
rm -rf var/cache/*/twig(适用于所有环境) - 用命令精准清理:
php bin/console twig:cache:clear --env=dev(Symfony 3.4+ 自带命令;低于此版本需手动删) - 若用了 APCu 做 Twig 模板缓存(通过
cache.adapter.apcu),还需执行apcu_clear_cache()或重启 PHP-FPM,否则内存里还留着旧字节码
模板内容被 CDN 或反向代理二次缓存
即使 Twig 缓存清了、页面也重新渲染了,用户看到的仍是旧 HTML——大概率是 Nginx、Varnish 或 Cloudflare 把整个响应体缓存了,根本没发请求到 PHP 层。
- 快速验证:curl -I http://yoursite.com/path,看响应头是否有
X-Symfony-Cache: GET /path: stale或Cache-Control: public, max-age=3600 - 临时禁用 HTTP 缓存:在控制器里加
$response->setPrivate()->setMaxAge(0),或全局在config/packages/framework.yaml中设framework.http_cache.max_age: 0 - CDN 层面:Cloudflare 需关闭 "Always Online" 和 "Auto Minify";自建 Varnish 要确认
vcl_hash没把 URL 参数或 Cookie 错误排除
最常被忽略的是:Twig 缓存开关和 HTTP 缓存开关是两套机制,改了一个不等于另一个同步更新;线上出问题时,90% 的“模板没更新”实际发生在反向代理层,而不是 PHP 里。


















