应优先用__public__:它指向public/目录,由app.public_path控制,静态资源(js/css/图片)用它更稳定;__root__返回请求url根路径,适用于跳转链接或api前缀等需动态适配部署路径的场景。

__ROOT__ 和 __PUBLIC__ 到底该用哪个?
模板里写 __ROOT__ 或 __PUBLIC__ 都能生成路径,但语义和适用场景完全不同:__ROOT__ 是当前请求的 URL 根(比如 /myapp 或 /),由 request()->root() 决定;__PUBLIC__ 默认是 __ROOT__/public,但实际值由配置项 app.public_path 控制。静态资源(CSS/JS/图片)必须放在 public/ 下,且应优先用 __PUBLIC__ —— 它更稳定,不随子目录部署变化而意外失效。
为什么直接写 /static/logo.png 会 404?
硬编码斜杠开头的路径是**绝对 URL 路径**,浏览器从域名根开始找文件。一旦部署在子目录(如 https://example.com/myapp/),请求就变成 https://example.com/static/logo.png,而真实路径其实是 https://example.com/myapp/public/static/logo.png。常见错误包括:
- 在模板里写
<img src="/static/logo.png"> - 误以为
ROOT_PATH可用于前端 URL(它是服务器文件系统路径,不能暴露给浏览器) - 把静态资源放在
public外(如项目根下的static/),又没改app.public_path
如何安全地自定义模板路径变量(比如 __ASSET__)?
不要魔改 __ROOT__ 或全局替换 tpl_replace_str,容易污染其他模板。推荐在控制器中显式赋值:
$this->assign('ASSET', config('app.cdn_url') ?: '__PUBLIC__');
然后模板里写 <script src="<?=%24ASSET?>/js/app.js"></script>。这样既能本地开发时指向 __PUBLIC__,上线后通过配置一键切 CDN,逻辑清晰、可测可控。注意:这个变量名不用双下划线,避免和框架内置变量冲突。
配置生效后为什么还是不替换?缓存陷阱在哪?
ThinkPHP 的模板替换是编译型的,修改 config/template.php 中的 tpl_replace_str 后,必须清除模板缓存才能生效。仅清浏览器缓存或 F5 刷新无效。执行命令:
php think clear:template
或者手动删掉 runtime/template/ 目录下所有文件。另外,如果你用了 {__CSS__} 这种带花括号的写法,那是 ThinkPHP 5.1 的语法要求——不加 {} 就不会触发替换,这点和 TP5.0 不同,容易被忽略。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











