跳到內容

Smarty 4遷移

本指南涵蓋從Smarty 3升級到Smarty 4時所需的更改和遷移步驟。理解這些差異對於維護與現代XOOPS安裝的相容性至關重要。

  • Smarty基礎知識 - XOOPS中Smarty的基礎
  • 主題開發 - 建立XOOPS主題
  • 範本變量 - 範本中可用的變量

Smarty 4從Smarty 3引入了幾個破壞性更改:

  1. 變量指派行為改變
  2. {php}標籤完全移除
  3. 快取API更改
  4. 修飾符處理更新
  5. 安全政策更改
  6. 移除已棄用的功能

在Smarty 2/3中,指派的值可直接訪問:

// PHP
$GLOBALS['xoopsTpl']->assign('mod_url', $helper->url());
{* Smarty 2/3 - 工作正常 *}
<img src="<{$mod_url}>/assets/images/icon.png">

在Smarty 4中,變量包裝在Smarty_Variable對象中:

Smarty_Variable Object
(
[value] => http://example.com/modules/mymodule/
[nocache] =>
)
{* Smarty 4 - 訪問value屬性 *}
<img src="<{$mod_url->value}>/assets/images/icon.png">

在PHP中啟用相容性模式:

$smarty = new Smarty();
$smarty->setCompatibilityMode(true);

這允許像Smarty 3一樣的直接變量訪問。

編寫在兩個版本中都可用的範本:

<{if $smarty.version|regex_replace:'[^0-9]':'' >= 4}>
<{$mod_url->value}>
<{else}>
<{$mod_url}>
<{/if}>

為指派建立幫助函數:

function smartyAssign($smarty, $name, $value)
{
if (version_compare($smarty->version, '4.0.0', '>=')) {
// Smarty 4+ - 正常指派,在範本中透過->value訪問
$smarty->assign($name, $value);
} else {
// Smarty 3 - 標準指派
$smarty->assign($name, $value);
}
}

Smarty 3+出於安全原因不支援{php}標籤:

{* 這在Smarty 3+中不再有效 *}
<{assign var="cid" value=$downloads.cid}>
<{php}>
$catid = $this->get_template_vars('cid');
<{/php}>
{* 使用Smarty的內置變量訪問 *}
<{assign var="cid" value=$downloads.cid}>
<{assign var="catid" value=$smarty.template_vars.cid}>

複雜邏輯應在PHP中,不在範本中:

// 在PHP中 - 進行處理
$catid = $downloads['cid'];
$categoryInfo = getCategoryInfo($catid);
// 將處理後的數據指派給範本
$GLOBALS['xoopsTpl']->assign('category', $categoryInfo);
{* 在範本中 - 只顯示 *}
<h2><{$category.name}></h2>

針對可重複使用的功能,建立Smarty插件:

/class/smarty/plugins/function.getcategory.php
function smarty_function_getcategory($params, $smarty)
{
$catId = $params['id'] ?? 0;
$categoryHandler = xoops_getModuleHandler('category', 'mymodule');
$category = $categoryHandler->get($catId);
if ($category) {
$smarty->assign($params['assign'], $category->toArray());
}
}
{* 在範本中 *}
<{getcategory id=$cid assign="category"}>
<h2><{$category.name}></h2>
// Smarty 3風格
$smarty->caching = true;
$smarty->cache_lifetime = 3600;
$smarty->cache_dir = '/path/to/cache';
// 個別變量nocache
$xoopsTpl->tpl_vars["mod_url"]->nocache = false;
// Smarty 4風格
$smarty->setCaching(Smarty::CACHING_LIFETIME_CURRENT);
$smarty->setCacheLifetime(3600);
$smarty->setCacheDir('/path/to/cache');
// 或使用屬性(仍然有效)
$smarty->caching = Smarty::CACHING_LIFETIME_CURRENT;
$smarty->cache_lifetime = 3600;
// 快取模式
Smarty::CACHING_OFF // 無快取
Smarty::CACHING_LIFETIME_CURRENT // 使用cache_lifetime
Smarty::CACHING_LIFETIME_SAVED // 使用快取生命週期
{* 標記內容為永遠不快取 *}
<{nocache}>
<p>Current time: <{$smarty.now|date_format:"%H:%M:%S"}></p>
<{/nocache}>

某些修飾符已重新命名或已棄用:

{* Smarty 3 *}
<{$text|escape:'htmlall'}>
{* Smarty 4 - 改用'html' *}
<{$text|escape:'html'}>

陣列修飾符需要@首碼:

{* 計算數組元素 *}
<{$items|@count}> items
{* 連接數組 *}
<{$tags|@implode:', '}>
{* JSON編碼 *}
<{$data|@json_encode}>

必須註冊自訂修飾符:

// 註冊自訂修飾符
$smarty->registerPlugin('modifier', 'my_modifier', 'my_modifier_function');
function my_modifier_function($string, $param1 = 'default')
{
// 處理並返回
return processed_string($string, $param1);
}

Smarty 4有更嚴格的預設安全性:

// 配置安全政策
$smarty->enableSecurity('Smarty_Security');
// 或建立自訂政策
class MySecurityPolicy extends Smarty_Security
{
public $php_functions = ['isset', 'empty', 'count'];
public $php_modifiers = ['escape', 'count'];
public $allow_super_globals = false;
}
$smarty->enableSecurity(new MySecurityPolicy($smarty));

預設情況下,Smarty 4限制可以使用的PHP函數:

{* 這些可能受限制 *}
<{if isset($variable)}>
<{if empty($array)}>
<{$array|@count}>

如果需要,配置允許的函數:

$smarty->security_policy->php_functions = [
'isset', 'empty', 'count', 'sizeof',
'in_array', 'is_array', 'date', 'time'
];

區塊語法基本相同,但有一些更改:

{* 父範本 *}
<html>
<head>
{block name=head}
<title>Default Title</title>
{/block}
</head>
<body>
{block name=content}{/block}
</body>
</html>
{* 子範本 *}
{extends file="parent.tpl"}
{block name=head}
{$smarty.block.parent} {* 包括父區塊內容 *}
<meta name="custom" content="value">
{/block}
{block name=content}
<h1>My Content</h1>
{/block}
{block name=head append}
{* 這在父內容之後新增 *}
<link rel="stylesheet" href="extra.css">
{/block}
{block name=scripts prepend}
{* 這在父內容之前新增 *}
<script src="early.js"></script>
{/block}
功能替代
{php}標籤將邏輯移到PHP或使用插件
{include_php}使用註冊的插件
$smarty.capture仍有效但已棄用
{strip}帶空格使用縮小化工具
{* 而不是{php} *}
{* 移到PHP並指派結果 *}
{* 而不是include_php *}
<{include file="db:mytemplate.tpl"}>
{* 而不是capture(仍有效但考慮) *}
<{capture name="sidebar"}>
<h3>Sidebar</h3>
<{/capture}>
<div><{$smarty.capture.sidebar}></div>
  1. 備份所有範本
  2. 列出所有{php}標籤使用
  3. 記錄自訂插件
  4. 測試當前功能
  1. 移除所有{php}標籤
  2. 更新變量訪問語法
  3. 檢查修飾符使用
  4. 更新快取配置
  5. 檢查安全設定
  1. 測試所有範本
  2. 檢查所有表單工作
  3. 驗證快取工作
  4. 用不同的用戶角色測試
// 檢查PHP中的Smarty版本
$version = Smarty::SMARTY_VERSION;
if (version_compare($version, '4.0.0', '>=')) {
// Smarty 4+特定代碼
} else {
// Smarty 3代碼
}
{* 檢查範本中的版本 *}
<{assign var="smarty_major" value=$smarty.version|regex_replace:'/\\..*$/':''}>
<{if $smarty_major >= 4}>
{* Smarty 4+範本代碼 *}
<{else}>
{* Smarty 3範本代碼 *}
<{/if}>
  1. 完全避免{php}標籤 - 它們在Smarty 3+中不起作用

  2. 保持範本簡單 - 複雜邏輯屬於PHP

  3. 使用標準修飾符 - 避免棄用的修飾符

  4. 在兩個版本中測試 - 如果您需要支援兩者

  5. 為複雜操作使用插件 - 更易於維護

{* 在Smarty 3和4中工作 *}
<!DOCTYPE html>
<html>
<head>
<title><{$page_title|default:'Default Title'|escape}></title>
</head>
<body>
<{if isset($items) && $items|@count > 0}>
<ul>
<{foreach $items as $item}>
<li><{$item.name|escape}></li>
<{/foreach}>
</ul>
<{else}>
<p>No items found.</p>
<{/if}>
</body>
</html>

問題<{$mod_url}>在Smarty 4中返回為空

解決方案:使用<{$mod_url->value}>或啟用相容性模式

問題:範本在{php}標籤上引發錯誤

解決方案:移除所有PHP標籤並將邏輯移到PHP檔案

問題:自訂修飾符引發「未知修飾符」錯誤

解決方案:使用registerPlugin()註冊修飾符

問題:範本中不允許函數

解決方案:將函數新增到安全政策的允許清單


#smarty #migration #upgrade #xoops #smarty4 #compatibility