开发环境应直接在config/template.php中设'cache' => false,而非依赖app_debug或删缓存;注意runtime/template/权限、opcache排除配置及模板路径须为ascii字符。

开发环境直接关 template.cache 就行
模板改了不生效,第一反应不是删缓存,而是确认是否还在用缓存。ThinkPHP 8.1 默认开启模板缓存,但开发阶段必须关——否则每次改 index.html 都要手动清 runtime/template/,纯属自我折磨。
打开 config/template.php,把这一项设为 false:
'cache' => false,
注意:别只改 .env 或其他配置文件,template 配置只认这个文件。改完立刻生效,无需重启服务、不用清缓存、不依赖 php think clear。
常见错误:
- 误以为
APP_DEBUG=true就自动禁用模板缓存——错,APP_DEBUG只影响配置和路由缓存,对template.cache无效 - 在
config/app.php里改template配置——无效,该配置不在那里加载
runtime/template/ 目录权限不对,关了也白关
即使 'cache' => false,某些情况下仍会生成缓存文件,比如 PHP 进程用户(如 www-data)对 runtime/template/ 有写权限,而框架检测到目录可写后“顺手”又写了进去——这不是 bug,是设计行为。
稳妥做法是让目录不可写(开发机上):
chmod 555 runtime/template/
或者干脆删掉它(框架会在需要时重建空目录):
rm -rf runtime/template/
如果删完报 TemplateException: template not exists,说明你模板路径写错了,或 view_path 配置指向了不存在的目录——这时候关缓存没用,得先修路径。
用了 {include} 或 {extend} 却还指望局部更新?别做梦了
ThinkPHP 8.1 的模板缓存是链式编译:一个 {extend file="layout"} + 若干 {include file="header"},最终合并成单个缓存文件。只要其中任一被包含文件变动,整个页面缓存全失效——听起来像好事?其实它导致两个真实问题:
- 你只改了
footer.html,结果首页、列表页、详情页的缓存全被清掉,重编译拖慢首次访问 - 你关了缓存(
'cache' => false),但引擎发现{include file="$dynamic_var"}这种动态变量写法,会直接跳过编译逻辑,转而每次 include 时实时读取文件——此时你看到的“更新”,其实是没走缓存的副作用,不是你关对了
正确做法:
- 稳定区块(如导航)用
{include file="common/nav" cache="3600"}显式加独立缓存 - 高频变动区块(如用户信息栏)改用
{widget name="user_info"}或前端 Ajax 加载 - 绝对不要在
{include}里传变量名:{include file="$tpl"}→ 缓存失效,且无法预编译
PHP 8.1+ 下 OPCache 会偷偷锁住旧模板内容
你确认 'cache' => false,删了 runtime/template/,甚至重启了 PHP-FPM,但浏览器还是加载旧 HTML——大概率是 OPCache 把某个模板编译后的 PHP 字节码缓存住了,且没排除 runtime/ 目录。
检查 php.ini 中这两项:
opcache.enable=1<br>opcache.file_exclude=".*runtime.*"
如果 file_exclude 没配,OPCache 会缓存 runtime/template/xxx.php 这类文件,哪怕你删了源文件,它仍从字节码里吐出旧内容。
临时验证方法:在控制器里加一行
opcache_reset();
如果加了这行就立刻更新,说明就是 OPCache 锁死。别用 opcache_invalidate() 精确清理——ThinkPHP 模板缓存文件名含哈希,你根本不知道它生成了哪个文件名。
真正容易被忽略的一点:PHP 8.1+ 对中文路径、emoji 的哈希结果不稳定,哪怕你路径里有个中文注释,都可能导致缓存文件名来回变,进而让清理动作打偏。模板路径保持纯 ASCII,是最省心的底线。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











