模板包含 Include

模板包含 Include

{include} 用于在一个模板里引入另一个模板(公共片段),如页头、页脚、分页条等。

一、语法

{include file="模板文件名" [变量1="值1" 变量2=$值2] [assign="变量名"]}
属性 必需 说明
file 是 要包含的模板资源名(相对 template_dir)
assign 否 将包含结果赋值给指定变量而非直接输出
其他属性 否 作为局部变量传递给子模板

二、示例

{include file="inc/header.tpl"}
{include file="inc/header.tpl" title=$page_title}
{include file="box.tpl" box=$box assign="box_html"}

{* 上面把 box.tpl 的渲染结果存进 $box_html,而不直接输出 *}
{$box_html nofilter}

三、子作用域隔离

{include} 编译为 $ctx->includeTemplate($file, $vars, $assignVar),运行期行为:

  • 包含前先保存当前作用域,把传入的具名变量合并进去;
  • 渲染子模板;
  • 渲染后恢复父作用域。因此子模板内部的变量(含子模板里的 {assign})不会回流到父级,避免了片段污染外层变量。

具名传参只在子模板可见:

{* 父模板 *}
{include file="inc/card.tpl" title="卡片标题" show=true}

子模板 inc/card.tpl 里可用 {$title} / {$show};但这些变量在父模板中并不存在。

四、assign 输出捕获

带 assign="变量名" 时,子模板的输出被 ob_start 捕获,写入父作用域的该变量,而不直接输出。适合「先把一段 HTML 组装成字符串、再决定怎么放」的场景。

五、递归防护 MAX_INCLUDE_DEPTH

子模板包含深度上限为 64(RenderContext::MAX_INCLUDE_DEPTH)。超过则抛 RuntimeException,防止模板自包含 / 互相包含导致无限递归耗尽调用栈。

六、资源名校验(安全)

file 的解析走 resolveTemplatePath,与「模板包含」相关的安全约束:

  • 扩展名白名单:只允许 .tpl / .htm / .html / .dwt;
  • 禁止路径穿越:资源名包含 ..、空字节、绝对路径或盘符均被拒绝;
  • 越界校验:解析后的真实路径必须仍在 template_dir 内(带目录分隔符前缀比较,防同前缀兄弟目录误通过)。

因此 file 应写相对资源名(如 inc/header.tpl),不要拼接用户输入、不要写绝对路径。

添加日期: