模板继承里 `__STATIC__` 别名在子主题覆盖后"叛变",我花了四十分钟才发现是 `view_replace_str` 的加载顺序在搞鬼

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

凌晨两点改一个子站点的皮肤,想着用 ThinkPHP 的模板继承省事:父级框架搭好,子主题只覆盖 `block` 里的内容,多干净。结果前端同事在群里甩了张截图——CSS 全站 404,页面跟 2003 年的表格布局似的。

我第一反应是 Nginx 路径配错了,或者 `public` 目录下 `static` 文件夹被谁误删。`ls` 一看,文件都在。再 F12 看请求地址,傻眼了:子主题居然在请求父级主题的 `__STATIC__/css/style.css`,而那个路径早就不存在了,子主题有自己的 `static` 目录。

问题出在 `config/view.php` 里的 `view_replace_str`。我为了"优雅",把全局的 `__STATIC__` 指向了父主题路径,想着子主题反正继承父级,用一套资源省事。但子主题的配置文件里我也写了一条 `__STATIC__`,打算覆盖成自己的路径。TP 加载配置的顺序是:模块配置 > 应用配置 > 惯例配置。看起来子主题的配置优先级更高对吧?

坑就在这里:模板继承的 `extend` 和 `include` 解析时,视图引擎先读的是父级模板的占位符替换,而父级模板里的 `__STATIC__` 在那时候已经被全局配置"固化"了。子主题配置虽然后加载,但父级模板解析阶段不会回头再换一遍。简单说,就是子主题的 `view_replace_str` 没机会覆盖父级模板里的别名。

我的"优雅"变成了"诡异"。最后解决办法很土:父级模板里不写死 `__STATIC__`,改成 `{$staticPath|default='__STATIC__'}`,子主题覆盖这个变量。或者更干脆的,子主题不用继承,直接复制一份框架模板——听起来 low,但维护成本反而更低,至少不会凌晨两点对着配置加载顺序怀疑人生。

后来翻 TP 源码,`think\template\TagLib` 那块的解析顺序确实跟配置合并顺序不完全同步。这种"看起来该生效"的配置陷阱,比明显的报错烦人一百倍。现在我的习惯是:凡是跨主题的资源路径,宁可写相对路径或者域名绝对路径,也不赌别名继承的行为。省下的那几行代码,不够付一次熬夜的咖啡钱。

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