在模板檔案中直接查詢資料庫並輸出,避免控制器傳遞大量資料,適用於側邊欄、導航選單、推薦區塊等通用片段。
路徑:ThinkPHP/Lib/Think/Template/TagLib/TagLibZpass.class.php (命名規則:TagLib{Name}.class.php)
<?php
namespace Think\Template\TagLib;
class TagLibZpass extends TagLib
{
// 標籤定義
protected $tags = [
'select' => [
'attr' => 'table,limit,order,where,field', // 支援屬性
'level' => 3, // 巢狀層級
'close' => 1, // 需閉合標籤
],
];
public function _select($attr, $content)
{
// 解析 XML 屬性
$tag = $this->parseXmlAttr($attr, 'table');
$table = $tag['table'];
// 快取機制:相同屬性+內容只解析一次
static $_cache = [];
$key = md5($attr . $content);
if (isset($_cache[$key])) {
return $_cache[$key];
}
// 查詢資料
$db = M($table);
$list = $db
->where($tag['where'])
->order($tag['order'])
->limit($tag['limit'])
->field($tag['field'])
->select();
// 解析模板內容中的 [field:xxx] 標記
preg_match_all('/\[field:(\w+)\]/', $content, $matches);
$fields = array_unique($matches[1]); // 去重
$parseStr = '';
foreach ($list as $i => $row) {
$itemStr = $content;
foreach ($fields as $field) {
$itemStr = str_replace("[field:{$field}]", $row[$field], $itemStr);
}
$parseStr .= $itemStr;
}
$_cache[$key] = $parseStr;
// 交給模板引擎進一步解析 (支援 {:U(...)} 等語法)
return $this->tpl->parse($parseStr);
}
}
?>
<!-- 引入標籤庫,name 對應 TagLib{Zpass} 的 Zpass -->
<taglib name="zpass" />
<!-- 使用 select 標籤 -->
<zpass:select
table="classes"
field="id,title"
order="sort desc"
limit="3"
where="status=1"
>
<span class="marginleft_1">
<a href="{:U('News/index', array('id=[field:id]'))}">[field:title]</a>
</span>
</zpass:select>
parseXmlAttr(){$var})靜態變數 $_cache 以 md5($attr.$content) 為鍵,避免同一頁面重複標籤重複查詢與解析。注意:快取鍵不包含資料庫狀態,資料更新後需清除模板編譯快取 (Runtime/Cache/) 才會重新查詢。
preg_match_all('/\[field:(\w+)\]/', ...) 擷取所有欄位標記array_unique 去重$list,逐行替換 [field:xxx] 為實際值return $this->tpl->parse($parseStr) 確保替換後的字串中若包含 {:U(...)}、{$var} 等 ThinkPHP 模板語法能正確編譯。
| 功能 | 實作方向 |
|---|---|
| 支援 join 查詢 | 新增 join、on 屬性,_select 中組裝 $db->join(...) |
| 支援分頁 | 整合 ThinkPHP Page 類,輸出分頁 HTML |
| 條件判斷標籤 | 新增 <zpass:if condition="...">...,呼叫 $this->parseCondition() |
| 資料快取 | 查詢前檢查 S('taglib_'.$key),命中則直接返回 |
| 命名空間支援 (TP5+) | 類別改為 app\taglib\Zpass,註冊於 config\taglib.php |
where 屬性直接傳入 ->where(),若允許使用者輸入需嚴格過濾或改用參數綁定。assign()。Runtime/Cache/ 目錄下編譯快取才生效。Lib/Think/Template/TagLib/;TP5/6 需註冊至 config/taglib.php 或使用 \think\facade\TagLib::register()。原作者:zpass (16852868@qq.com) | 整理補充:命名空間規範、快取機制解析、安全性警示、版本差異、進階擴充方向