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

SmartyBC 相容性包裝類別完整原始碼解析:從 Smarty 2 遷移至 Smarty 3

     編輯:PHP 綜合知識

背景

Smarty 3 重寫核心架構,API 命名風格改為駝峰式 (camelCase),且移除部分舊方法。SmartyBC (Backward Compatibility) 類別繼承 Smarty,提供 Smarty 2 風格的方法別名,讓舊專案零修改升級至 Smarty 3。

完整類別原始碼 (精簡註解版)

<?php
require_once dirname(__FILE__) . '/Smarty.class.php';

/**
 * Smarty 2 相容性包裝類別
 */
class SmartyBC extends Smarty {
    public $_version = self::SMARTY_VERSION;

    public function __construct(array $options = []) {
        parent::__construct($options);
        // 註冊 {php}{/php} 標籤 (Smarty 3 預設移除)
        $this->registerPlugin('block', 'php', 'smarty_php_tag');
    }

    // === 指派變數 ===
    public function assign_by_ref($tpl_var, &$value) {
        $this->assignByRef($tpl_var, $value);
    }
    public function append_by_ref($tpl_var, &$value, $merge = false) {
        $this->appendByRef($tpl_var, $value, $merge);
    }
    public function clear_assign($tpl_var) {
        $this->clearAssign($tpl_var);
    }

    // === 註冊外掛 (Smarty 2 風格方法名) ===
    public function register_function($function, $function_impl, $cacheable = true, $cache_attrs = null) {
        $this->registerPlugin('function', $function, $function_impl, $cacheable, $cache_attrs);
    }
    public function unregister_function($function) {
        $this->unregisterPlugin('function', $function);
    }
    public function register_object($object, $object_impl, $allowed = [], $smarty_args = true, $block_methods = []) {
        $this->registerObject($object, $object_impl, $allowed, $smarty_args, $block_methods);
    }
    public function unregister_object($object) {
        $this->unregisterObject($object);
    }
    public function register_block($block, $block_impl, $cacheable = true, $cache_attrs = null) {
        $this->registerPlugin('block', $block, $block_impl, $cacheable, $cache_attrs);
    }
    public function unregister_block($block) {
        $this->unregisterPlugin('block', $block);
    }
    public function register_compiler_function($function, $function_impl, $cacheable = true) {
        $this->registerPlugin('compiler', $function, $function_impl, $cacheable);
    }
    public function unregister_compiler_function($function) {
        $this->unregisterPlugin('compiler', $function);
    }
    public function register_modifier($modifier, $modifier_impl) {
        $this->registerPlugin('modifier', $modifier, $modifier_impl);
    }
    public function unregister_modifier($modifier) {
        $this->unregisterPlugin('modifier', $modifier);
    }

    // === 資源管理 ===
    public function register_resource($type, $functions) {
        $this->registerResource($type, $functions);
    }
    public function unregister_resource($type) {
        $this->unregisterResource($type);
    }

    // === 過濾器 ===
    public function register_prefilter($function) {
        $this->registerFilter('pre', $function);
    }
    public function unregister_prefilter($function) {
        $this->unregisterFilter('pre', $function);
    }
    public function register_postfilter($function) {
        $this->registerFilter('post', $function);
    }
    public function unregister_postfilter($function) {
        $this->unregisterFilter('post', $function);
    }
    public function register_outputfilter($function) {
        $this->registerFilter('output', $function);
    }
    public function unregister_outputfilter($function) {
        $this->unregisterFilter('output', $function);
    }
    public function load_filter($type, $name) {
        $this->loadFilter($type, $name);
    }

    // === 快取管理 ===
    public function clear_cache($tpl_file = null, $cache_id = null, $compile_id = null, $exp_time = null) {
        return $this->clearCache($tpl_file, $cache_id, $compile_id, $exp_time);
    }
    public function clear_all_cache($exp_time = null) {
        return $this->clearCache(null, null, null, $exp_time);
    }
    public function is_cached($tpl_file, $cache_id = null, $compile_id = null) {
        return $this->isCached($tpl_file, $cache_id, $compile_id);
    }

    // === 變數管理 ===
    public function clear_all_assign() {
        $this->clearAllAssign();
    }
    public function clear_compiled_tpl($tpl_file = null, $compile_id = null, $exp_time = null) {
        return $this->clearCompiledTemplate($tpl_file, $compile_id, $exp_time);
    }

    // === 工具方法 ===
    public function template_exists($tpl_file) {
        return $this->templateExists($tpl_file);
    }
    public function get_template_vars($name = null) {
        return $this->getTemplateVars($name);
    }
    public function get_config_vars($name = null) {
        return $this->getConfigVars($name);
    }
    public function config_load($file, $section = null, $scope = 'global') {
        $this->ConfigLoad($file, $section, $scope);
    }
    public function get_registered_object($name) {
        return $this->getRegisteredObject($name);
    }
    public function clear_config($var = null) {
        $this->clearConfig($var);
    }
    public function trigger_error($error_msg, $error_type = E_USER_WARNING) {
        trigger_error("Smarty error: $error_msg", $error_type);
    }
}

/**
 * {php}{/php} 區塊外掛實作
 * 允許模板中直接執行 PHP 程式碼 (極度不建議,安全風險高)
 */
function smarty_php_tag($params, $content, $template, &$repeat) {
    eval($content);
    return '';
}

方法對照表:Smarty 2 → Smarty 3 / SmartyBC

Smarty 2 (舊)Smarty 3 (新)SmartyBC 別名說明
assign_by_refassignByRef✓ assign_by_ref參考指派變數
append_by_refappendByRef✓ append_by_ref參考追加陣列元素
clear_assignclearAssign✓ clear_assign清除指派變數
register_functionregisterPlugin('function',...)✓ register_function註冊自訂函式標籤
register_objectregisterObject✓ register_object註冊物件供模板存取
register_blockregisterPlugin('block',...)✓ register_block註冊區塊標籤
register_modifierregisterPlugin('modifier',...)✓ register_modifier註冊修飾器
register_resourceregisterResource✓ register_resource註冊模板資源來源
register_prefilterregisterFilter('pre',...)✓ register_prefilter編譯前過濾
register_postfilterregisterFilter('post',...)✓ register_postfilter編譯後過濾
register_outputfilterregisterFilter('output',...)✓ register_outputfilter輸出過濾
load_filterloadFilter✓ load_filter載入過濾器
clear_cacheclearCache✓ clear_cache清除快取
clear_all_cacheclearCache(null...)✓ clear_all_cache清除所有快取
is_cachedisCached✓ is_cached檢查快取是否存在
template_existstemplateExists✓ template_exists檢查模板是否存在
get_template_varsgetTemplateVars✓ get_template_vars取得指派變數
config_loadConfigLoad✓ config_load載入設定檔
trigger_errortrigger_error✓ trigger_error觸發錯誤

遷移指南:從 Smarty 2 升級至 Smarty 3

1. 直接替換類別名稱 (最快)

// 舊
require 'Smarty.class.php';
$smarty = new Smarty();

// 新:零程式碼修改
require 'SmartyBC.class.php';
$smarty = new SmartyBC();

2. 漸進式遷移至 Smarty 3 原生 API

require 'Smarty.class.php';
$smarty = new Smarty();

// 新風格指派
$smarty->assign('name', 'John');
$smarty->assign(['title' => 'Manager', 'dept' => 'IT']);

// 新風格註冊外掛
$smarty->registerPlugin('function', 'my_func', 'myFuncImpl');
$smarty->registerPlugin('modifier', 'upper', 'strtoupper');

// 新風格快取
$smarty->setCaching(Smarty::CACHING_LIFETIME_CURRENT);
$smarty->setCacheLifetime(3600);

3. 移除 {php} 標籤 (強烈建議)

SmartyBC 為相容而註冊 smarty_php_tag,但 模板中執行 PHP 是嚴重安全漏洞。遷移步驟:

  1. 搜尋所有模板中的 {php}...{/php}。
  2. 將邏輯移至 PHP 控制器,透過 assign() 傳遞資料。
  3. 或撰寫自訂外掛函式/修飾器封裝邏輯。
  4. 停用 SmartyBC,改用 Smarty,不註冊 php tag。

常見遷移問題與解決

問題原因解決
模板變數不顯示Smarty 3 預設 error_unassigned = false,未指派變數輸出空字串而非報錯設定 $smarty->error_unassigned = true 開發環境啟用
模板繼承 {block} 不生效Smarty 3 區塊語法與 Smarty 2 不同改用 {block name='x'}...{/block} 與 {extends file='layout.tpl'}
修飾器管道符號優先序變化Smarty 3 嚴格遵循左至右加上括號明確分組:{$var|modifier1|modifier2} → {($var|modifier1)|modifier2}
編譯後模板路徑不同Smarty 3 使用 compile_id、子目錄清除 templates_c/ 重新編譯

現代替代方案建議

若專案允許重構,建議遷移至現代模板引擎:

  • Twig:Symfony 標準,語法優雅、安全、效能佳、支援繼承/區塊/宏/沙箱。
  • Blade:Laravel 內建,編譯為原生 PHP、語法簡潔、支援元件/插槽。
  • Latte:Nette 框架,強調安全 (自動逃逸)、效能極佳、TypeScript 風格型別提示。

SmartyBC 讓舊專案能平滑過渡至 Smarty 3,但長遠規劃應逐步移除舊式 API 依賴,並評估遷移至現代模板引擎以獲得更好的開發體驗與安全性。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved