Skip to content

{foreach},{foreachelse}

{foreach}用于遍历数据数组。{foreach}{section}循环的语法更简单、更清晰,并且还可以遍历关联数组。

选项标志

名称 描述
nocache 禁用{foreach}循环的缓存

示例

{foreach $arrayvar as $itemvar}
  {$itemvar|escape}
{/foreach}

{foreach $arrayvar as $keyvar=>$itemvar}
  {$keyvar}: {$itemvar|escape}
{/foreach}

注意

这种 foreach 语法不接受任何命名属性。这种语法是 Smarty 3 的新特性,但是 Smarty 2.x 的语法{foreach from=$myarray key="mykey" item="myitem"}仍然受支持。

  • {foreach}循环可以嵌套。

  • array变量,通常是值的数组,决定了{foreach}将循环的次数。你也可以传递一个整数进行任意循环。

  • array变量中没有值时,执行{foreachelse}

  • {foreach}的属性有@index@iteration@first@last@show@total

  • {foreach}的构造有{break}{continue}

  • 你可以通过{$item@key}访问循环项的当前键,而不是指定key变量(见下面的示例)。

注意

$var@property语法是 Smarty 3 的新特性,然而,当使用 Smarty 2 的{foreach from=$myarray key="mykey" item="myitem"}风格的语法时,$smarty.foreach.name.property语法仍然受支持。

注意

尽管你可以用{foreach $myArray as $myKey => $myValue}语法获取数组键,但在 foreach 循环中,键始终以$myValue@key的形式可用。

<?php
$arr = array('red', 'green', 'blue');
$smarty->assign('myColors', $arr);

模板输出$myColors为无序列表

<ul>
    {foreach $myColors as $color}
        <li>{$color}</li>
    {/foreach}
</ul>

上述示例将输出:

<ul>
  <li>red</li>
  <li>green</li>
  <li>blue</li>
</ul>
<?php
$people = array('fname' => 'John', 'lname' => 'Doe', 'email' => 'j.doe@example.com');
$smarty->assign('myPeople', $people);

模板输出$myArray为键值对。

<ul>
    {foreach $myPeople as $value}
       <li>{$value@key}: {$value}</li>
    {/foreach}
</ul>

上述示例将输出:

<ul>
  <li>fname: John</li>
  <li>lname: Doe</li>
  <li>email: j.doe@example.com</li>
</ul>

将数组分配给 Smarty,键包含每个循环值的键。

<?php
 $smarty->assign(
    'contacts',
    [
         ['phone' => '555-555-1234', 'fax' => '555-555-5678', 'cell' => '555-555-0357'],
         ['phone' => '800-555-4444', 'fax' => '800-555-3333', 'cell' => '800-555-2222'],
     ]
 );

输出$contact的模板。

{* key always available as a property *}
{foreach $contacts as $contact}
  {foreach $contact as $value}
    {$value@key}: {$value}
  {/foreach}
{/foreach}

{* accessing key the PHP syntax alternate *}
{foreach $contacts as $contact}
  {foreach $contact as $key => $value}
    {$key}: {$value}
  {/foreach}
{/foreach}

上述两个示例都会输出:

  phone: 555-555-1234
  fax: 555-555-5678
  cell: 555-555-0357
  phone: 800-555-4444
  fax: 800-555-3333
  cell: 800-555-2222

数据库(PDO)示例,遍历搜索结果。此示例正在遍历 PHP 迭代器,而不是数组()。

<?php
  include('Smarty.class.php');

  $smarty = new Smarty;

  $dsn = 'mysql:host=localhost;dbname=test';
  $login = 'test';
  $passwd = 'test';

  // setting PDO to use buffered queries in mysql is
  // important if you plan on using multiple result cursors
  // in the template.

  $db = new PDO($dsn, $login, $passwd, array(
     PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true));

  $res = $db->prepare("select * from users");
  $res->execute();
  $res->setFetchMode(PDO::FETCH_LAZY);

  // assign to smarty
  $smarty->assign('res',$res);

  $smarty->display('index.tpl');?>
{foreach $res as $r}
  {$r.id}
  {$r.name}
{foreachelse}
  .. no results ..
{/foreach}

以上假定结果包含名为idname的列。

迭代器与遍历普通旧数组的优势是什么?对于数组,所有的结果在循环之前都被积累到内存中。对于迭代器,每个结果在循环中被加载/释放。这节省了处理时间和内存,尤其是对于非常大的结果集。

@index

index包含当前数组索引,从零开始。

{* output empty row on the 4th iteration (when index is 3) *}
<table>
    {foreach $items as $i}
      {if $i@index eq 3}
         {* put empty table row *}
         <tr><td>nbsp;</td></tr>
      {/if}
      <tr><td>{$i.label}</td></tr>
    {/foreach}
</table>

@iteration

iteration包含当前循环的迭代次数,始终从一开始,不像index。它在每次迭代时增加一。

可以使用"is div by"运算符来检测特定的迭代。这里我们在每 4 次迭代时将名字加粗。

{foreach $myNames as $name}
  {if $name@iteration is div by 4}
    <b>{$name}</b>
  {/if}
  {$name}
{/foreach}

"is even by""is odd by"运算符可以用来在每隔几次迭代时交替某个东西。选择偶数或奇数决定了哪一个开始。这里我们每隔 3 次迭代切换字体颜色。

 {foreach $myNames as $name}
   {if $name@iteration is even by 3}
     <span style="color: #000">{$name}</span>
   {else}
     <span style="color: #eee">{$name}</span>
   {/if}
 {/foreach}

这将输出类似于这样的内容:

<span style="color: #000">...</span>
<span style="color: #000">...</span>
<span style="color: #000">...</span>
<span style="color: #eee">...</span>
<span style="color: #eee">...</span>
<span style="color: #eee">...</span>
<span style="color: #000">...</span>
<span style="color: #000">...</span>
<span style="color: #000">...</span>
<span style="color: #eee">...</span>
<span style="color: #eee">...</span>
<span style="color: #eee">...</span>
...

@first

如果当前的{foreach}迭代是初始的,那么first为 TRUE。这里我们在第一次迭代时显示一个表头行。

{* show table header at first iteration *}
<table>
    {foreach $items as $i}
      {if $i@first}
        <tr>
          <th>key</td>
          <th>name</td>
        </tr>
      {/if}
      <tr>
        <td>{$i@key}</td>
        <td>{$i.name}</td>
      </tr>
    {/foreach}
</table>

@last

如果当前的{foreach}迭代是最后一次,那么last被设置为 TRUE。这里我们在最后一次迭代时显示一个水平线。

{* Add horizontal rule at end of list *}
{foreach $items as $item}
  <a href="#{$item.id}">{$item.name}</a>{if $item@last}<hr>{else},{/if}
{foreachelse}
  ... no items to loop ...
{/foreach}

@show

show属性可以在执行{foreach}循环后用来检测是否显示了数据。show是一个布尔值。

<ul>
    {foreach $myArray as $name}
        <li>{$name}</li>
    {/foreach}
</ul>
{if $name@show} do something here if the array contained data {/if}

@total

total包含了这个{foreach}将循环的次数。这可以在{foreach}内部或之后使用。

{* show number of rows at end *}
{foreach $items as $item}
  {$item.name}<hr/>
  {if $item@last}
    <div id="total">{$item@total} items</div>
  {/if}
{foreachelse}
 ... no items to loop ...
{/foreach}

参见 {section}{for}{while}

{break}

{break}终止数组的迭代

  {$data = [1,2,3,4,5]}
  {foreach $data as $value}
    {if $value == 3}
      {* abort iterating the array *}
      {break}
    {/if}
    {$value}
  {/foreach}
  {*
    prints: 1 2
  *}

{continue}

{continue}离开当前迭代并开始下一次迭代。

  {$data = [1,2,3,4,5]}
  {foreach $data as $value}
    {if $value == 3}
      {* skip this iteration *}
      {continue}
    {/if}
    {$value}
  {/foreach}
  {*
    prints: 1 2 4 5
  *}