跳至内容

{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} 的循环次数。您还可以传递一个整数表示任意循环。

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

  • {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 
  use Smarty\Smarty;

  $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 开始。它在每个迭代中加 1。

“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@index 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 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
  *}