{foreach} 循环标签

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

smarty 模板 foreach if
(图片来源网络,侵删)

基本语法

{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} 循环提供了一些非常有用的内置变量,用于控制循环行为或获取循环状态:

smarty 模板 foreach if
(图片来源网络,侵删)
  • {@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 模板文件中:

smarty 模板 foreach if
(图片来源网络,侵删)
{* 基本条件判断 *}
{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>

代码解释:

  1. {foreach $products as $product}: 开始遍历 $products 数组。
  2. {if $product.price > 50}: 在循环内部,判断当前产品的价格是否大于 50。
  3. {if @first}: 如果是循环中的第一个元素(并且价格也大于50),则给它添加一个 first-item 的 CSS 类。
  4. {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}