🔄 模板变量
ThinkAdmin 提供完善的模板替换变量系统,支持多种路径类型的自动替换,简化模板开发。
📚 基础概念
什么是模板变量?
模板变量是在 HTML 模板文件中使用的特殊标记(如 __ROOT__、__APP__ 等),系统在渲染模板时会自动将这些标记替换为实际的路径或值。
简单理解:就像 Word 文档中的"占位符",系统会自动填充真实内容。
举个例子:
<!-- 在模板中写 -->
<script src="__ROOT__/static/js/app.js"></script>
<!-- 系统自动替换为 -->
<script src="/static/js/app.js"></script>为什么需要模板变量?
在 Web 开发中,我们经常需要在 HTML 中引用各种资源文件(CSS、JavaScript、图片等)。如果直接写死路径,会遇到很多问题:
问题1:硬编码路径难以维护
<!-- ❌ 不推荐:硬编码路径 -->
<script src="/static/js/app.js"></script>
<link rel="stylesheet" href="/static/css/admin.css">如果网站部署到子目录(如 https://domain.com/project/),所有路径都需要修改。
问题2:不同环境路径不同
- 开发环境:
http://localhost/ - 生产环境:
https://domain.com/ - 测试环境:
https://test.domain.com/
使用模板变量后:
<!-- ✅ 推荐:使用模板变量 -->
<script src="__ROOT__/static/js/app.js"></script>
<link rel="stylesheet" href="__ROOT__/static/css/admin.css">系统会根据当前环境自动替换为正确的路径。
模板变量的优势:
- 路径统一管理:所有路径通过变量统一管理,修改时只需改一处
- 环境自动适配:不同环境(开发、生产)可以自动使用不同的路径
- 代码更简洁:使用变量比硬编码路径更简洁易读
- 易于维护:路径变更时无需修改所有模板文件
模板变量的工作流程
模板变量的替换过程是自动的,无需手动处理:
步骤1:在模板中使用变量
<!-- 模板文件:app/admin/view/index.html -->
<script src="__ROOT__/static/js/app.js"></script>步骤2:系统解析模板时自动替换 ThinkAdmin 在渲染模板时,会自动识别 __ROOT__ 等变量,并根据当前环境替换为实际路径。
步骤3:输出最终 HTML
<!-- 最终输出给浏览器 -->
<script src="/static/js/app.js"></script>技术细节:
- 替换发生在模板渲染阶段(
$this->fetch()时) - 替换结果会被缓存,提升性能
- 支持多种变量类型,满足不同场景需求
相关概念说明
模板(Template)
- 用于显示页面的 HTML 文件
- 位于
app/*/view/目录 - 使用 ThinkPHP 模板引擎解析
- 支持变量、循环、条件判断等语法
变量替换
- 将模板中的变量标记替换为实际值的过程
- 在模板渲染时自动完成
- 支持缓存机制,提升性能
静态资源
- CSS、JavaScript、图片等不需要服务器处理的文件
- 通常存储在
public/static/目录 - 通过 Web 服务器直接访问,不经过 PHP 处理
🚀 主要功能
- 路径替换: 自动替换模板中的路径变量
- 多类型支持: 支持动态路径、静态路径、应用路径等
- 灵活配置: 支持自定义路径配置
- 自动解析: 自动解析和替换路径变量
- 第三方支持: 支持生成第三方资源链接
- 开发简化: 简化模板开发中的路径处理
📋 变量类型
ThinkAdmin 提供了四种模板变量,用于不同场景的路径替换:
__APP__ - 动态路径
__APP__ 用于加载需要通过 PHP 处理的动态脚本文件,系统会自动替换为包含入口文件的完整路径。
什么是动态路径?
- 动态路径包含入口文件(如
/index.php) - 请求会经过 PHP 处理,可以执行权限验证、数据处理等
- 适合加载需要服务器端处理的脚本
替换规则:
<!-- 模板中 -->
<script src="__APP__/admin/api/data"></script>
<!-- 替换后 -->
<script src="/index.php/admin/api/data"></script>使用场景:
- 加载需要权限验证的 API 数据
<!-- 用户管理页面,加载用户列表(需要登录验证) -->
<script>
$.get('__APP__/admin/user/list', function(data) {
console.log(data);
});
</script>
<!-- 替换后:$.get('/index.php/admin/user/list', ...) -->- 加载动态生成的 JavaScript 配置
<!-- 页面初始化,加载系统配置 -->
<script src="__APP__/admin/config/js"></script>
<!-- 替换后:/index.php/admin/config/js -->
<!-- 这个接口会返回动态生成的 JavaScript 代码 -->- AJAX 请求接口
<script>
// 提交表单数据
$.post('__APP__/admin/user/save', {
name: '张三',
email: 'zhangsan@example.com'
}, function(result) {
if (result.code === 1) {
alert('保存成功');
}
});
</script>技术细节:
__APP__会替换为/index.php(或配置的入口文件)- 请求会经过 ThinkPHP 路由系统
- 支持权限验证、中间件等处理
- 适合需要服务器端逻辑的场景
__ROOT__ - 静态路径
__ROOT__ 用于加载静态资源文件,系统会自动替换为网站根路径(不包含入口文件)。
什么是静态路径?
- 静态路径不包含入口文件,直接指向资源文件
- 请求不经过 PHP 处理,由 Web 服务器直接返回
- 适合加载 CSS、JavaScript、图片等静态文件
替换规则:
<!-- 模板中 -->
<link rel="stylesheet" href="__ROOT__/static/css/admin.css">
<!-- 替换后 -->
<link rel="stylesheet" href="/static/css/admin.css">使用场景:
- 加载 CSS 样式文件
<!-- 页面头部引入样式 -->
<head>
<!-- 框架基础样式 -->
<link rel="stylesheet" href="__ROOT__/static/plugs/admin/css/admin.css">
<!-- 自定义样式 -->
<link rel="stylesheet" href="__ROOT__/static/css/custom.css">
</head>- 加载 JavaScript 文件
<!-- 页面底部引入脚本 -->
<script src="__ROOT__/static/plugs/admin/js/admin.js"></script>
<script src="__ROOT__/static/js/custom.js"></script>- 加载图片资源
<!-- 显示图片 -->
<img src="__ROOT__/static/images/logo.png" alt="Logo">
<!-- 背景图片 -->
<div style="background-image: url(__ROOT__/static/images/bg.jpg);"></div>- 完整的页面示例
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>后台管理</title>
<!-- 使用 __ROOT__ 加载静态 CSS -->
<link rel="stylesheet" href="__ROOT__/static/plugs/admin/css/admin.css">
</head>
<body>
<div class="container">
<h1>欢迎使用 ThinkAdmin</h1>
<!-- 使用 __ROOT__ 加载图片 -->
<img src="__ROOT__/static/images/logo.png" alt="Logo">
</div>
<!-- 使用 __ROOT__ 加载静态 JavaScript -->
<script src="__ROOT__/static/plugs/admin/js/admin.js"></script>
</body>
</html>技术细节:
__ROOT__会替换为/(网站根路径)- 请求直接由 Web 服务器(Nginx/Apache)处理
- 不经过 PHP,性能更好
- 适合静态资源文件(CSS、JS、图片等)
__PLUG__ - 应用路径
__PLUG__ 用于加载当前应用专属的静态资源,系统会自动替换为应用专属路径。
什么是应用路径?
- 每个应用(如
admin、index)都有专属的资源目录 - 资源存储在
public/static/extra/{应用名}/目录 - 不同应用的资源互不干扰,便于管理
替换规则:
<!-- 在 admin 应用的模板中 -->
<script src="__PLUG__/js/custom.js"></script>
<!-- 替换后 -->
<script src="/static/extra/admin/js/custom.js"></script>目录结构说明:
public/
└── static/
└── extra/
├── admin/ # admin 应用的专属资源
│ ├── js/
│ ├── css/
│ └── images/
└── index/ # index 应用的专属资源
├── js/
└── css/使用场景:
- 加载应用专属的 JavaScript
<!-- admin 应用的用户管理页面 -->
<script src="__PLUG__/js/user-manage.js"></script>
<!-- 替换后:/static/extra/admin/js/user-manage.js -->
<!-- 这个文件只属于 admin 应用,其他应用不会加载 -->- 加载应用专属的 CSS
<!-- admin 应用的自定义样式 -->
<link rel="stylesheet" href="__PLUG__/css/admin-custom.css">
<!-- 替换后:/static/extra/admin/css/admin-custom.css -->- 加载应用专属的图片
<!-- admin 应用的专属图标 -->
<img src="__PLUG__/images/admin-icon.png" alt="Admin Icon">
<!-- 替换后:/static/extra/admin/images/admin-icon.png -->- 多应用场景对比
<!-- admin 应用的模板 -->
<script src="__PLUG__/js/admin.js"></script>
<!-- 替换后:/static/extra/admin/js/admin.js -->
<!-- index 应用的模板 -->
<script src="__PLUG__/js/index.js"></script>
<!-- 替换后:/static/extra/index/js/index.js -->技术细节:
__PLUG__会根据当前应用名自动替换- 在
admin应用中,替换为/static/extra/admin/ - 在
index应用中,替换为/static/extra/index/ - 不同应用的资源完全隔离,避免冲突
__FULL__ - 完整路径
__FULL__ 用于生成完整的 URL 链接,包含协议(http/https)和域名,通常用于需要完整 URL 的场景。
什么是完整路径?
- 完整路径包含:
协议://域名/路径 - 例如:
https://www.example.com/static/images/logo.png - 适合需要完整 URL 的场景(如分享链接、API 回调等)
替换规则:
<!-- 模板中 -->
<img src="__FULL__/static/images/logo.png" alt="Logo">
<!-- 替换后(假设域名是 https://v6.thinkadmin) -->
<img src="https://v6.thinkadmin/static/images/logo.png" alt="Logo">使用场景:
- 生成分享链接
<!-- 文章分享功能 -->
<a href="__FULL__/article/123" target="_blank">分享文章</a>
<!-- 替换后:https://v6.thinkadmin/article/123 -->
<!-- 微信分享需要完整 URL -->
<script>
var shareUrl = '__FULL__/article/123';
// 替换后:https://v6.thinkadmin/article/123
// 可以用于微信分享、QQ 分享等
</script>- 生成图片完整链接
<!-- 在邮件中嵌入图片 -->
<img src="__FULL__/static/images/logo.png" alt="Logo">
<!-- 替换后:https://v6.thinkadmin/static/images/logo.png -->
<!-- 用于二维码内容 -->
<div id="qrcode" data-url="__FULL__/article/123"></div>- API 回调地址
<!-- 支付回调地址 -->
<form action="https://pay.example.com/pay">
<input type="hidden" name="notify_url" value="__FULL__/api/payment/notify">
<!-- 替换后:https://v6.thinkadmin/api/payment/notify -->
</form>- 社交媒体分享
<!-- 分享到微博 -->
<a href="https://service.weibo.com/share/share.php?url=__FULL__/article/123" target="_blank">
分享到微博
</a>
<!-- 分享到微信(需要生成二维码) -->
<script>
var wechatUrl = '__FULL__/article/123';
// 可以用于生成微信分享二维码
</script>技术细节:
__FULL__会根据当前请求自动获取协议和域名- HTTP 请求替换为
http:// - HTTPS 请求替换为
https:// - 域名从当前请求中自动获取
- 适合需要完整 URL 的外部调用场景
🔧 工作原理
自动替换机制
模板变量的替换是在模板渲染时自动完成的,无需手动处理。
替换时机:
- 当调用
$this->fetch()渲染模板时 - ThinkPHP 模板引擎会自动识别变量标记
- 根据当前环境自动替换为实际路径
替换过程:
// 1. 控制器渲染模板
public function index()
{
return $this->fetch(); // 触发模板渲染
}
// 2. 模板引擎解析
// 模板内容:<script src="__ROOT__/static/js/app.js"></script>
// 3. 自动替换变量
// 替换后:<script src="/static/js/app.js"></script>
// 4. 输出最终 HTML性能优化:
- 替换结果会被缓存,避免重复计算
- 缓存存储在
runtime/cache/目录 - 修改模板后会自动更新缓存
路径生成规则
系统根据当前请求自动生成正确的路径:
__ROOT__ 生成规则:
// 当前请求:https://www.example.com/admin/index
// __ROOT__ 替换为:/__APP__ 生成规则:
// 当前请求:https://www.example.com/admin/index
// __APP__ 替换为:/index.php
// 完整路径:/index.php/admin/index__PLUG__ 生成规则:
// 当前应用:admin
// __PLUG__ 替换为:/static/extra/admin/__FULL__ 生成规则:
// 当前请求:https://www.example.com/admin/index
// __FULL__ 替换为:https://www.example.com环境适配
不同环境下,路径会自动适配:
开发环境:
<!-- 模板中 -->
<script src="__FULL__/static/js/app.js"></script>
<!-- 开发环境替换后 -->
<script src="http://localhost/static/js/app.js"></script>生产环境:
<!-- 模板中 -->
<script src="__FULL__/static/js/app.js"></script>
<!-- 生产环境替换后 -->
<script src="https://www.example.com/static/js/app.js"></script>子目录部署:
<!-- 模板中 -->
<script src="__ROOT__/static/js/app.js"></script>
<!-- 部署在子目录:https://www.example.com/project/ -->
<!-- 替换后 -->
<script src="/project/static/js/app.js"></script>💡 完整示例
在模板中使用
模板变量会在模板渲染时自动替换,无需额外处理:
<!DOCTYPE html>
<html>
<head>
<!-- 使用 __ROOT__ 加载静态 CSS -->
<link rel="stylesheet" href="__ROOT__/static/css/admin.css">
<!-- 使用 __PLUG__ 加载应用专属 CSS -->
<link rel="stylesheet" href="__PLUG__/css/custom.css">
</head>
<body>
<!-- 使用 __FULL__ 生成完整图片链接 -->
<img src="__FULL__/static/images/logo.png" alt="Logo">
<!-- 使用 __APP__ 加载动态脚本 -->
<script src="__APP__/admin/api/init"></script>
<!-- 使用 __ROOT__ 加载静态 JavaScript -->
<script src="__ROOT__/static/js/app.js"></script>
</body>
</html>在控制器中获取路径
如果需要在控制器中获取替换后的路径,可以使用以下方法:
<?php
declare(strict_types=1);
namespace app\admin\controller;
use think\admin\Controller;
class Example extends Controller
{
public function index()
{
// 获取动态路径
$appUrl = $this->app->request->domain() . '/index.php';
// 获取根路径
$rootUrl = $this->app->request->domain();
// 获取应用专属路径
$plugUrl = $this->app->request->domain() . '/static/extra/' . $this->app->request->module();
// 获取完整 URL
$fullUrl = $this->app->request->domain() . '/static';
// 传递给模板
$this->assign([
'appUrl' => $appUrl,
'rootUrl' => $rootUrl,
'plugUrl' => $plugUrl,
'fullUrl' => $fullUrl,
]);
return $this->fetch();
}
}在 PHP 代码中使用系统函数
ThinkAdmin 提供了 sysuri() 函数来获取路径:
<?php
// 获取动态路径(包含入口文件)
$appUrl = sysuri();
// 输出:/index.php
// 获取根路径
$rootUrl = sysuri('');
// 输出:/
// 获取完整 URL(包含协议和域名)
$fullUrl = sysuri('', true);
// 输出:https://domain.com
// 生成完整资源链接
$imageUrl = sysuri('/static/images/logo.png', true);
// 输出:https://domain.com/static/images/logo.png⚠️ 注意事项
使用建议
选择合适的变量类型:
__APP__- 动态路径- ✅ 适合:需要权限验证的 API 接口
- ✅ 适合:动态生成的 JavaScript 配置
- ✅ 适合:需要服务器端处理的请求
- ❌ 不适合:静态资源文件(性能较差)
__ROOT__- 静态路径- ✅ 适合:CSS、JavaScript、图片等静态文件
- ✅ 适合:框架提供的公共资源
- ✅ 适合:所有应用共享的资源
- ❌ 不适合:需要权限验证的资源
__PLUG__- 应用路径- ✅ 适合:应用专属的 CSS、JavaScript
- ✅ 适合:应用特定的图片资源
- ✅ 适合:需要隔离的应用资源
- ❌ 不适合:多个应用共享的资源
__FULL__- 完整路径- ✅ 适合:分享链接、API 回调地址
- ✅ 适合:邮件中嵌入的图片
- ✅ 适合:需要完整 URL 的外部调用
- ❌ 不适合:页面内部的资源引用(性能较差)
常见错误
错误1:在静态资源中使用 __APP__
<!-- ❌ 错误:静态文件不需要经过 PHP -->
<script src="__APP__/static/js/app.js"></script>
<!-- ✅ 正确:使用 __ROOT__ -->
<script src="__ROOT__/static/js/app.js"></script>错误2:在页面内部使用 __FULL__
<!-- ❌ 错误:页面内部不需要完整 URL -->
<link rel="stylesheet" href="__FULL__/static/css/admin.css">
<!-- ✅ 正确:使用 __ROOT__ -->
<link rel="stylesheet" href="__ROOT__/static/css/admin.css">错误3:跨应用使用 __PLUG__
<!-- ❌ 错误:在 admin 应用中引用 index 应用的资源 -->
<script src="__PLUG__/js/index.js"></script>
<!-- 会替换为:/static/extra/admin/js/index.js(错误) -->
<!-- ✅ 正确:使用 __ROOT__ 引用公共资源 -->
<script src="__ROOT__/static/js/index.js"></script>性能优化
缓存机制:
- 变量替换结果会被缓存到
runtime/cache/目录 - 首次访问时替换并缓存,后续直接使用缓存
- 修改模板后会自动更新缓存
CDN 支持:
- 可以通过配置将静态资源指向 CDN
- 提升静态资源的加载速度
- 减少服务器带宽压力
最佳实践:
- 静态资源优先使用
__ROOT__(性能最好) - 动态请求使用
__APP__(功能完整) - 应用专属资源使用
__PLUG__(隔离清晰) - 外部调用使用
__FULL__(完整 URL)
