{foreach} 循环标签
{foreach} 用于在模板中遍历一个数组,并为数组的每个元素生成一段 HTML,这是 Smarty 中处理列表数据最主要的方式。

(图片来源网络,侵删)
基本语法
{foreach $array_name as $value}
<!-- 循环体 -->
{ $value }
{/foreach}
高级语法(推荐)
更常用的是 key => value 的形式,这样可以同时获取元素的键名和值。
{foreach $array_name as $key => $value}
<!-- 循环体 -->
<p>键: { $key }, 值: { $value }</p>
{/foreach}
示例
假设你的 PHP 文件中传递了如下的数据给 Smarty:
<?php
// assign_array.php
require_once 'libs/Smarty.class.php';
$smarty = new Smarty;
// 定义一个简单的索引数组
$smarty->assign('users', [
'Alice',
'Bob',
'Charlie'
]);
// 定义一个关联数组(更常见)
$smarty->assign('products', [
['id' => 1, 'name' => 'Laptop', 'price' => 1200],
['id' => 2, 'name' => 'Mouse', 'price' => 25],
['id' => 3, 'name' => 'Keyboard', 'price' => 75]
]);
$smarty->display('index.tpl');
?>
在 index.tpl 模板文件中,你可以这样使用 {foreach}:
{* 遍历简单的索引数组 *}
<h2>用户列表</h2>
<ul>
{foreach $users as $user}
<li>{ $user }</li>
{/foreach}
</ul>
{* 遍历关联数组(推荐方式) *}
<h2>产品列表</h2>
<table border="1">
<tr>
<th>ID</th>
<th>产品名称</th>
<th>价格</th>
</tr>
{foreach $products as $product}
<tr>
<td>{ $product.id }</td>
<td>{ $product.name }</td>
<td>${ $product.price }</td>
</tr>
{/foreach}
</table>
{foreach} 的特殊变量
{foreach} 循环提供了一些非常有用的内置变量,用于控制循环行为或获取循环状态:

(图片来源网络,侵删)
{@iteration}: 当前循环的次数(从 1 开始)。{@index}: 当前循环的索引(从 0 开始)。{@first}: 如果是第一次循环,此变量为true。{@last}: 如果是最后一次循环,此变量为true。{@show}: 控制是否显示当前循环的内容,设置为false可以跳过本次迭代。
示例:使用特殊变量
<h2>产品列表(带序号和特殊标记)</h2>
<table border="1">
<tr>
<th>序号</th>
<th>产品名称</th>
<th>价格</th>
<th>标记</th>
</tr>
{foreach $products as $product}
<tr {if @last} style="font-weight: bold;" {/if}>
<td>{ @iteration }</td>
<td>{ $product.name }</td>
<td>${ $product.price }</td>
<td>
{if @first}
<span style="color: green;">新品</span>
{elseif @last}
<span style="color: red;">清仓</span>
{/if}
</td>
</tr>
{/foreach}
</table>
{if} 条件判断标签
{if} 用于根据不同的条件显示不同的内容,其语法和 PHP 的 if/elseif/else 非常相似。
基本语法
{if condition}
<!-- 条件为真时显示 -->
{elseif condition2}
<!-- 第一个条件为假,且第二个条件为真时显示 -->
{else}
<!-- 所有条件都为假时显示 -->
{/if}
支持的运算符
- 比较运算符: , ,
>,<,>=,<= - 逻辑运算符:
and,or,not, - 其他:
is even: 判断是否为偶数。is odd: 判断是否为奇数。is div by: 判断是否能被某数整除。is not empty: 判断变量是否非空。is empty: 判断变量是否为空。
示例
假设你的 PHP 文件中传递了如下数据:
<?php
// assign_conditions.php
require_once 'libs/Smarty.class.php';
$smarty = new Smarty;
$smarty->assign('user_logged_in', true);
$smarty->assign('user_role', 'admin');
$smarty->assign('product_count', 5);
$smarty->assign('welcome_message', '欢迎回来!');
$smarty->display('conditions.tpl');
?>
在 conditions.tpl 模板文件中:

(图片来源网络,侵删)
{* 基本条件判断 *}
{if $user_logged_in}
<p>欢迎回来,您已登录!</p>
{else}
<p>请先<a href="login.php">登录</a>。</p>
{/if}
{* 使用 elseif 和逻辑运算符 *}
{if $user_role == 'admin'}
<p>您是管理员,可以访问所有页面。</p>
{elseif $user_role == 'editor'}
<p>您是编辑,可以发布和修改文章。</p>
{else}
<p>您是普通用户。</p>
{/if}
{* 使用特殊判断 *}
<p>当前有 { $product_count } 件商品。</p>
{if $product_count > 0}
<p class="success">库存充足!</p>
{/if}
{if $product_count is div by 2}
<p>商品数量是偶数。</p>
{/if}
{if $welcome_message is not empty}
<h3>{ $welcome_message }</h3>
{/if}
{foreach} 和 {if} 的结合使用
在实际开发中,我们经常需要在循环内部进行条件判断,只显示价格大于 100 的商品,或者给第一个或最后一个元素添加特殊的 CSS 类。
示例:在循环中筛选和标记
继续使用上面的 $products 数据。
<h2>高价产品列表(> 50美元)</h2>
<ul>
{foreach $products as $product}
{if $product.price > 50}
<li {if @first} class="first-item" {/if}>
<strong>{ $product.name }</strong> - ${ $product.price }
</li>
{/if}
{foreachelse}
<p>没有找到符合条件的产品。</p>
{/foreach}
</ul>
代码解释:
{foreach $products as $product}: 开始遍历$products数组。{if $product.price > 50}: 在循环内部,判断当前产品的价格是否大于 50。{if @first}: 如果是循环中的第一个元素(并且价格也大于50),则给它添加一个first-item的 CSS 类。{foreachelse}: 这是一个非常有用的部分,如果传入的$products数组是空的,{foreach}循环体不会执行,而是直接执行{foreachelse}和{/foreach}之间的内容,这对于处理空数据列表非常友好。
总结与最佳实践
| 用途 | 关键点 | |
|---|---|---|
{foreach} |
遍历数组,渲染列表数据。 | 优先使用 key => value 形式,熟练使用 @first, @last, @iteration 等内置变量。 |
{if} |
根据条件显示或隐藏内容。 | 语法清晰,支持丰富的运算符,注意 is empty 等特殊判断。 |
| 结合使用 | 在列表中根据元素的属性进行条件渲染。 | 将 {if} 放在 {foreach} 循环内部,可以实现对列表项的精细控制。 |
注意事项:
- 变量修饰符: Smarty 允许在变量后使用修饰符,这有时可以替代一些
{if}判断。{ $var|lower }将变量转为小写。 - 性能:
{foreach}和{if}是 Smarty 的核心功能,性能已经过优化,但在复杂的模板中,避免在循环内部执行过于复杂的逻辑判断。 - 代码可读性: 保持模板的简洁和可读性,如果逻辑过于复杂,应该考虑将其移至 PHP 控制器中处理,而不是在模板里堆砌大量的
{if}和{foreach}。
