首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

Smarty 自定義資源插件實現從數據庫讀取模板

     編輯:PHP 綜合知識

背景

Smarty 默認從文件系統讀取模板。通過自定義資源插件,可實現從數據庫、Redis、遠程 API 等任意數據源加載模板,滿足動態模板、多租戶、版本控制等高級需求。

核心接口:四個回調函數

註冊資源時需提供四個函數,對應模板生命週期的關鍵節點:

函數職責參數返回值
get_template讀取模板源碼$tpl_name, &$tpl_source, &$smartytrue/false
get_timestamp獲取模板最後修改時間戳(用於緩存判斷)$tpl_name, &$tpl_timestamp, &$smartytrue/false
get_secure安全性檢查(如防止目錄遍歷)$tpl_name, &$smartytrue/false
get_trusted可信檢查({include} 等標簽調用時)$tpl_name, &$smartytrue/false

完整實現示例:從 MySQL 讀取模板

<?php
// 假設已有資料庫封裝類 SQL
function db_get_template($tpl_name, &$tpl_source, &$smarty_obj) {
    $sql = new SQL;
    $sql->query("SELECT tpl_source FROM my_templates WHERE tpl_name = '$tpl_name'");
    if ($sql->num_rows) {
        $tpl_source = $sql->record['tpl_source'];
        return true;
    }
    return false;
}

function db_get_timestamp($tpl_name, &$tpl_timestamp, &$smarty_obj) {
    $sql = new SQL;
    $sql->query("SELECT tpl_timestamp FROM my_templates WHERE tpl_name = '$tpl_name'");
    if ($sql->num_rows) {
        $tpl_timestamp = (int)$sql->record['tpl_timestamp'];
        return true;
    }
    return false;
}

function db_get_secure($tpl_name, &$smarty_obj) {
    // 簡單示例:僅允許字母數字下劃線
    return preg_match('/^[a-zA-Z0-9_]+$/', $tpl_name);
}

function db_get_trusted($tpl_name, &$smarty_obj) {
    // 模板包含時不額外檢查
    return true;
}

// 註冊資源名稱為 "db"
$smarty->register_resource("db", array(
    "db_get_template",
    "db_get_timestamp",
    "db_get_secure",
    "db_get_trusted"
));

// 使用:資源名:模板名
$smarty->display("db:index.tpl");
?>

進階應用建議

  • 緩存層:在 get_template 中引入 Redis/Memcached 緩存模板內容,減少 DB 查詢。
  • 版本控制:數據表增加 version 字段,get_timestamp 返回版本號或更新時間,配合 Smarty 編譯緩存實現熱更新。
  • 多租戶隔離:tpl_name 可設計為 tenant_id:template_name 格式,在回調中解析租戶 ID。
  • 回滾機制:保留歷史版本記錄,通過管理後台一鍵回滾模板內容。

注意事項

  1. 資源名稱(示例中 db)必須唯一,避免與內置 file、eval 等衝突。
  2. get_timestamp 返回的時間戳必須為整數,Smarty 据此判斷是否重新編譯。
  3. get_secure 應嚴格校驗模板名,防止路徑遍歷或注入攻擊。
  4. 模板內容中若包含 {php} 標簽,需確保 security_policy 允許或自行過濾。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved