Discuz! 的模板引擎是一个 “PHP 模板引擎”,它的工作核心思想是 “逻辑与表现分离”。

- 逻辑:指 PHP 代码,负责数据处理、数据库查询、业务逻辑判断等。
- 表现:指 HTML 模板文件,负责页面的最终展示,包含 HTML、CSS 和一些特殊的模板标签。
模板引擎就像一个“翻译官”,它读取模板文件,将其中特殊的模板标签“翻译”成最终的 PHP 代码,然后执行这些代码,并将 PHP 变量的值填充到相应位置,最终生成用户浏览器可以直接解析的 HTML 代码。
核心流程:从 PHP 到 HTML
整个过程可以分为三个主要步骤:
-
PHP 端:准备数据
- 在 PHP 文件中,你通过常规的 PHP 代码(如数据库查询
DB::query()、数组处理等)获取需要展示的数据。 - 将这些数据赋值给一个或多个 PHP 变量。
- 在 PHP 文件中,你通过常规的 PHP 代码(如数据库查询
-
交接:调用模板引擎
(图片来源网络,侵删)- PHP 端使用
include template('模板名称');这个函数来请求输出一个模板。 - 这个函数会触发 Discuz! 的模板引擎。
- PHP 端使用
-
模板端:展示数据
- 模板引擎找到并加载
template/当前风格/模板名称.htm文件。 - 引擎解析这个
.htm文件,遇到模板标签时,会用 PHP 端准备好的变量值进行替换。 - 解析完成后,生成一个临时的 PHP 文件(通常在
data/template/目录下)。 - 服务器执行这个临时 PHP 文件,将最终的 HTML 输出到浏览器。
- 模板引擎找到并加载
模板语法详解
Discuz! 的模板语法非常直观,它使用花括号 来包裹其特殊指令。
变量输出
这是最基本的功能,用于显示 PHP 传递过来的变量。
-
简单变量:
// PHP 代码中 $username = '张三'; $age = 25; // 模板代码中 欢迎您,{$_G[username]}!您的年龄是:{$age} -
数组/对象变量: 使用 来访问数组的元素或对象的属性。
// PHP 代码中 $userInfo = array( 'name' => '李四', 'profile' => array( 'city' => '北京', 'job' => '工程师' ) ); // 模板代码中 用户名:{$userInfo.name} 城市:{$userInfo.profile.city} -
全局变量
$_G:$_G是 Discuz! 中最重要的全局变量数组,包含了当前用户、站点设置、会话信息等所有全局数据。站点名称:{$_G['site']['name']} 当前用户UID:{$_G['uid']}
条件判断 if
if 标签用于根据条件来决定是否输出某部分内容。
<!-- 基本用法 -->
{if $age > 18}
您已成年。
{else}
您未成年。
{/if}
<!-- 多重条件 -->
{if $usergroup == 'admin'}
您是管理员。
{elseif $usergroup == 'mod'}
您是版主。
{else}
您是普通用户。
{/if}
<!-- 判断变量是否存在或为空 -->
{if !empty($post['message'])}
帖子内容:{$post['message']}
{/if}
循环遍历 loop
loop 标签用于遍历一个数组,对数组中的每一个元素重复执行一段代码。
这是在列表页(如帖子列表、用户列表)中最常用的标签。
<!-- 假设 $threadlist 是一个包含多个主题信息的数组 -->
<!-- {loop $threadlist $thread} -->
<!-- 循环开始,$thread 是当前循环到的元素,相当于 PHP 中的 $thread -->
<li>
<a href="forum.php?mod=viewthread&tid={$thread['tid']}">
{$thread['subject']}
</a>
<span>作者:{$thread['author']}</span>
<span>回复:{$thread['replies']}</span>
</li>
<!-- {/loop} -->
语法解析:
{loop $array $key => $value}
$array: 要遍历的数组。$key: 可选,当前元素的键名。$value: 当前元素的值。
示例:
{loop $userlist $uid $user}
用户ID: {$uid}, 用户名: {$user['username']}
{/loop}
引入子模板 template
在一个模板文件中,可以引入另一个模板文件,用于实现模块化,例如页头、页脚、侧边栏等。
<!-- 在 forumdisplay.htm 中 -->
{template header} <!-- 引入头部模板 template/default/header.htm -->
{template forumlist} <!-- 引入版块列表模板 -->
<!-- 主要内容区 -->
{loop $threadlist $thread}
...
{/loop}
{template footer} <!-- 引入底部模板 template/default/footer.htm -->
注释
在模板文件中,使用 包裹的内容会被引擎忽略,不会输出到 HTML 中,非常适合写注释。
{这是一个模板注释,不会在源代码中看到}
实践示例:修改帖子列表的标题颜色
假设我们想把置顶帖子的标题显示为红色。
第1步:找到对应的 PHP 文件
帖子列表通常在 forum/forumdisplay.php 文件中处理,打开它,找到生成 $threadlist 数组的核心代码段。
第2步:在 PHP 中添加判断逻辑
在 forumdisplay.php 中,找到处理 $threadlist 的循环(通常在 while($thread = DB::fetch($query)) 循环里),添加一个变量来标记帖子是否为置顶。
// ... 在 forumdisplay.php 的循环中 ...
while($thread = DB::fetch($query)) {
// 原有的代码...
// 添加我们的逻辑
if($thread['displayorder'] > 0) {
$thread['title_color'] = 'red'; // 如果是置顶(displayorder > 0),设置颜色变量
} else {
$thread['title_color'] = '#333'; // 否则使用默认颜色
}
// ... 继续原有的代码 ...
}
第3步:找到并修改对应的模板文件
帖子列表的模板文件通常是 template/default/forum/forumdisplay.htm。
第4步:在模板中使用新变量
打开 forumdisplay.htm,找到显示帖子标题的代码,将原来的 {$thread['subject']} 修改为带有样式的版本。
<!-- 原来的代码可能是这样的 -->
<a href="forum.php?mod=viewthread&tid={$thread['tid']}">{$thread['subject']}</a>
<!-- 修改为如下代码 -->
<a href="forum.php?mod=viewthread&tid={$thread['tid']}" style="color: {$thread['title_color']};">
{if $thread['displayorder'] > 0}[置顶] {/if}
{$thread['subject']}
</a>
第5步:清空缓存并刷新
模板修改后,需要清空 Discuz! 的缓存,否则可能看不到效果。 进入 后台 -> 工具 -> 更新缓存,更新“模板缓存”,然后刷新论坛页面,你就会看到置顶帖子的标题变成了红色。
进阶技巧与注意事项
-
模板缓存: Discuz! 会将解析后的模板编译成 PHP 文件存放在
data/template/目录下,以提高访问速度,当你修改了模板文件后,必须更新缓存才能生效。 -
eval函数: 有时你需要在模板中执行一小段复杂的 PHP 代码,可以使用eval{eval $hello = 'Hello from eval!';} {echo $hello}注意:滥用
eval会破坏“逻辑与表现分离”的原则,使模板难以维护,应尽量避免。 -
函数调用: 你可以在模板中直接调用一些 PHP 函数来处理变量。
{date('Y-m-d', $timestamp)} <!-- 调用 date 函数格式化时间戳 --> {strtoupper($username)} <!-- 调用 strtoupper 函数将用户名转为大写 -->可用的函数是有限的,主要是为了安全考虑。
-
继承与区块(
{block}): 在较新版本的 Discuz! 中,支持类似 PHP 面向对象中“继承”的模板机制,父模板可以定义一个{block}区块,子模板可以{block}的name属性来覆盖父模板中的内容,这为制作主题提供了极大的灵活性。
通过掌握以上内容,你就可以对 Discuz! 的前台显示进行几乎任何你想要的修改了,核心就是 “PHP 准备数据 -> include template 调用 -> 模板语法展示” 这个流程。
