Smarty 作為經典 PHP 模板引擎,雖然提倡「業務邏輯與展示分離」,但在模板中偶爾需要定義變量、訪問常量、進行簡單運算。本文系統總結 Smarty 3.x 中的變量賦值、常量訪問、數學運算與循環計數器技巧。
PHP 端定義:define('SITE_NAME', 'MySite');
{* 模板中訪問 *}
{$smarty.const.SITE_NAME}
{* 輸出: MySite *}
{$smarty.const.常量名}{* 定義字符串 *}
{assign var="userName" value="zhangsan"}
{* 定義數字(無需引號) *}
{assign var="count" value=10}
{* 定義陣列 *}
{assign var="tags" value=['php', 'smarty', 'template']}
{* 定義對象屬性 *}
{assign var="user" value=$userObj}
{* 輸出 *}
用戶名: {$userName}
計數: {$count}
標簽: {$tags|@join:', '}
{$userName = "zhangsan"}
{$count = 10}
{$tags = ['php', 'smarty']}
推薦使用短語法,更簡潔、符合直覺。
Smarty 不支持 ++、--、+=、-= 等簡寫運算符。
{* 加法 *}
{$a = $a + 1}
{* 或使用 math 插件 *}
{math equation="x + 1" x=$a assign=a}
{* 減法 *}
{$b = $b - 1}
{* 乘除 *}
{$c = $a * $b}
{$d = $a / $b}
{* 取模 *}
{$e = $a % 3}
{* 複雜表達式 *}
{math equation="(x + y) * z" x=2 y=3 z=4 assign=result}
{* result = 20 *}
{* 格式化輸出 *}
{math equation="x / y" x=10 y=3 assign=ratio format="%.2f"}
{* ratio = 3.33 *}
Smarty {foreach} 無內置計數器,需手動實現。
{$i = 0}
{foreach $items as $item}
<div class="item-{$i}">
{$item.name} - 第 {$i + 1} 條
</div>
{$i = $i + 1}
{/foreach}
{section name=loop loop=$items}
{$items[loop].name} - 索引: {$smarty.section.loop.index} (從0開始)
{$items[loop].name} - 迭代: {$smarty.section.loop.iteration} (從1開始)
{$items[loop].name} - 是否首項: {if $smarty.section.loop.first}是{else}否{/if}
{$items[loop].name} - 是否尾項: {if $smarty.section.loop.last}是{else}否{/if}
{/section}
{foreach $items as $item}
{$item@index} {* 0-based 索引 *}
{$item@iteration} {* 1-based 迭代次數 *}
{$item@first} {* 是否第一項 *}
{$item@last} {* 是否最後項 *}
{$item@show} {* 是否顯示(受 if 條件影響) *}
{$item@total} {* 總項數 *}
{/foreach}
最推薦方法三,語義清晰、無需額外變量、性能最好。
{* 外層循環 *}
{$outerIndex = 0}
{foreach $categories as $category}
<div class="category category-{$outerIndex}">
<h3>{$category.name}</h3>
<ul>
{* 內層循環使用 @iteration *}
{foreach $category.articles as $article}
<li class="article-{$article@iteration}">
<a href="{$article.url}" target="_blank">{$article.title}</a>
{if $article@first}<span class="new">最新</span>{/if}
</li>
{/foreach}
</ul>
</div>
{$outerIndex = $outerIndex + 1}
{/foreach}
| 場景 | 推薦做法 | 避免做法 |
|---|---|---|
| 複雜業務計算 | PHP 控制器預計算好,模板只輸出 | 模板中大量 {math}、{assign} 邏輯 |
| 循環計數 | 使用 $item@iteration / $item@index | 手動 {$i=$i+1} 易出錯 |
| 條件判斷 | PHP 端預處理標誌位,模板用 {if $flag} | 模板中嵌套複雜 {if}{elseif} |
| 變量賦值 | 短語法 {$var = val} | 舊式 {assign var=...} |
| 常量訪問 | {$smarty.const.CONST_NAME} | PHP 端 assign 到模板 |
若模板確需複雜邏輯,編寫 Smarty 插件(放入 plugins/ 目錄):
<?php
// plugins/function.calc.php
function smarty_function_calc($params, $template) {
$equation = $params['equation'] ?? '';
$vars = $params;
unset($vars['equation'], $vars['assign']);
$result = @eval("return $equation;"); // 注意安全
if (isset($params['assign'])) {
$template->assign($params['assign'], $result);
} else {
return $result;
}
}
?>
{* 模板調用 *}
{calc equation="x * y + z" x=2 y=3 z=4 assign=total}
{$total} {* 10 *}
Smarty 模板的設計初衷是簡單展示,盡量將計算、邏輯下沉到 PHP 控制器/視圖模型層。善用 @iteration、@index、math 插件處理簡單運算,複雜邏輯交給 PHP,保持模板乾淨、可維護、易前端協作。