模板继承里 `block` 没闭合,我花了两小时才发现样式表在子页面"断尾"

小助手
小助手 版主圣羽星庭 勋望元宿志愿先锋
社区管理
站长杂谈 73 浏览 0 回复

上周给后台做主题切换功能,想着用 ThinkPHP6 的模板继承把公共骨架抽出来,结果踩了个特别隐蔽的坑——子页面里一个 `{block name="css"}{/block}` 没写闭合标签,导致后面整段 HTML 被吞进 block 内容里,浏览器解析到一半直接放弃加载剩下的样式表。

表象特别迷惑:F12 看 Elements,head 里明明有 `` 标签,但 Styles 面板就是空的。我一度怀疑是静态资源发布路径配错了,把 `__STATIC__/admin/css` 改成绝对路径、加版本号、甚至手动写死 CDN 域名,全都没用。

最后是靠把页面源码复制到本地,用编辑器高亮对比才发现的。子模板里我抄了一段旧的 block 写法,开头是 `{block name="css"}`,结尾却写成了 `{/block name="css"}`——ThinkPHP 的模板引擎其实不认这种带 name 的闭合标签,它直接把从 `{block name="css"}` 开始到页面末尾第一个 `{/block}` 之间的所有内容都吞进去了。那个倒霉的 `{/block}` 刚好在页面底部,于是 head 里的 link 标签虽然生成了,但后面跟着一堆被误吞的 body 内容,浏览器解析到 `

` 出现在 `` 里,直接触发" foster parenting ",把 link 丢出去或者干脆忽略。

更坑的是,这个问题只在特定条件下复现。如果子页面没定义 `css` block,它会回退到父模板的默认内容,一切正常;一旦我尝试覆盖加自定义样式,闭合标签写错就触发 bug。我本地测试时大部分页面没自定义样式,上线后运营同事在新模块里加了段日期选择器的 skin,整页直接"裸奔"。

说回静态资源发布路径,这次折腾让我重新梳理了一遍 TP6 的资源处理逻辑。`php think publish` 命令会把 `public/static` 下的资源复制到运行目录,但很多人没注意它实际读的是 `config/view.php` 里的 `tpl_replace_string` 配置。我项目里之前为了兼容旧域名,把 `__STATIC__` 配成了 `//cdn.example.com/static`,结果 HTTPS 页面里混了个 HTTP 的内嵌资源,又触发了一次混合内容拦截。后来改成协议相对路径 `//` 开头,但发现某些企业内网环境没外网 DNS,CDN 域名解析失败,最后还是老老实实换回相对路径 `/static`,靠 Nginx 同域代理或者干脆把资源包打进部署包。

现在我的模板继承规范多了两条硬规矩:一是所有 block 必须在一屏内写完,超过五行就拆文件 include;二是子模板覆盖 block 时,先用 `{block name="css"}{__block__}{/block}` 把父级内容原样输出,再追加自己的,防止遗漏。另外给 IDE 装了个 ThinkPHP 模板高亮插件,虽然不完美,但至少 `{/block}` 这种基础语法错误能标红了。

你们模板继承里还遇到过什么玄学问题?我这次算是被一个小小的闭合标签上了一课——有时候不是路径错了,是标签"没闭嘴"。

评论0
回复 · 0
还没有回复
微信客服 微信客服