模板标签开发手册
模板标签处理器、参数、缓存、标签生成器声明和安全性能要求。
模板标签开发手册
模板标签用于把结构化数据交给主题模板,不用于输出整块固定页面。新增标签应优先返回数据、URL、状态和链接数组,HTML 输出只作为兼容或低层组件能力。
标签类型
| 类型 | 示例 | 说明 |
|---|---|---|
| 数据标签 | {content}、{category}、{search} |
读取数据并建立循环上下文 |
| URL 标签 | {category_url}、{member_url} |
生成页面地址 |
| 资源标签 | {theme_asset}、{plugin_asset} |
生成资源地址 |
| 业务标签 | {member_order} |
由模块或插件提供业务状态 |
| 兼容 HTML 标签 | {thumb_img}、{file_link} |
输出小片段 HTML |
处理器接口
运行时标签处理器实现:
use App\Cms\Templates\Contracts\TemplateTagHandlerContract;
use App\Cms\Templates\TemplateRenderContext;
class FriendLinksTag implements TemplateTagHandlerContract
{
public function names(): array
{
return ['friend_links'];
}
public function render(string $name, array $attributes, string $body, TemplateRenderContext $context): string
{
// 读取参数、查询服务、渲染循环体
}
}
注册:
app(TemplateTagRegistry::class)->register(app(FriendLinksTag::class));
参数规则
标签参数必须转换为声明式条件:
{content model=article catid=$category.id num=10 order=new return=t}
处理器需要校验:
- 模型、栏目、字段是否存在。
- 排序值是否在允许列表中。
- 数量和分页是否超过上限。
- 字段条件是否属于可查询字段。
- 当前会员态、游客态是否允许读取。
不得让模板传入 SQL 片段、任意表名、任意字段表达式或未受控 join。
循环变量
官方示例约定:
| 场景 | 默认变量 |
|---|---|
| 内容列表 | $t |
| 栏目列表 | $t 或自定义 return=c |
| 搜索结果 | $rs |
| 详情页 | $title、$content、$fields.xxx.text |
新增标签应支持 return 参数,避免多个标签嵌套时变量冲突。
空数据分支
数据标签应支持 {empty}:
{friend_links group=home return=link}
<a href="{$link.url}">{$link.title}</a>
{empty}
<span>暂无链接</span>
{/empty}
{/friend_links}
缓存与性能
标签处理器需要考虑:
- 游客态和会员态缓存不同。
- 模型、栏目、字段、主题和插件变化后缓存失效。
- 循环中嵌套标签容易产生 N+1 查询,应批量取数。
- 列表标签必须限制
num、pagesize和危险排序。 - 慢标签应记录来源、参数和耗时,便于排查。
标签生成器声明
模块或插件可以在 manifest 中声明 template_tags,供标签生成器展示:
{
"template_tags": [
{
"value": "friend_links",
"label": "友情链接",
"snippet": "{friend_links group={{group}} return={{return}}}...{/friend_links}",
"defaults": {
"group": "home",
"return": "link"
}
}
]
}
template_tags 只声明生成器展示项,不注册运行时处理器。真正的标签仍由 ServiceProvider 注册。
安全输出
- 普通变量默认安全转义。
- 富文本、已清洗 HTML 或系统低层渲染器输出才允许
{html ...}。 - 插件返回的内容默认当作用户输入处理。
- 标签处理器不得把未经清洗的请求参数拼入 HTML、SQL 或文件路径。