408 lines
9.5 KiB
Markdown
408 lines
9.5 KiB
Markdown
{foreach},{foreachelse} {#language.function.foreach}
|
|
=======================
|
|
|
|
`{foreach}` is used for looping over arrays of data. `{foreach}` has a
|
|
simpler and cleaner syntax than the
|
|
[`{section}`](#language.function.section) loop, and can also loop over
|
|
associative arrays.
|
|
|
|
`{foreach $arrayvar as $itemvar}`
|
|
|
|
`{foreach $arrayvar as $keyvar=>$itemvar}`
|
|
|
|
> **Note**
|
|
>
|
|
> This foreach syntax does not accept any named attributes. This syntax
|
|
> is new to Smarty 3, however the Smarty 2.x syntax
|
|
> `{foreach from=$myarray key="mykey" item="myitem"}` is still
|
|
> supported.
|
|
|
|
- `{foreach}` loops can be nested.
|
|
|
|
- The `array` variable, usually an array of values, determines the
|
|
number of times `{foreach}` will loop. You can also pass an integer
|
|
for arbitrary loops.
|
|
|
|
- `{foreachelse}` is executed when there are no values in the `array`
|
|
variable.
|
|
|
|
- `{foreach}` properties are [`@index`](#foreach.property.index),
|
|
[`@iteration`](#foreach.property.iteration),
|
|
[`@first`](#foreach.property.first),
|
|
[`@last`](#foreach.property.last),
|
|
[`@show`](#foreach.property.show),
|
|
[`@total`](#foreach.property.total).
|
|
|
|
- `{foreach}` constructs are [`{break}`](#foreach.construct.break),
|
|
[`{continue}`](#foreach.construct.continue).
|
|
|
|
- Instead of specifying the `key` variable you can access the current
|
|
key of the loop item by `{$item@key}` (see examples below).
|
|
|
|
> **Note**
|
|
>
|
|
> The `$var@property` syntax is new to Smarty 3, however when using the
|
|
> Smarty 2 `{foreach from=$myarray key="mykey" item="myitem"}` style
|
|
> syntax, the `$smarty.foreach.name.property` syntax is still supported.
|
|
|
|
> **Note**
|
|
>
|
|
> Although you can retrieve the array key with the syntax
|
|
> `{foreach $myArray as $myKey => $myValue}`, the key is always
|
|
> available as `$myValue@key` within the foreach loop.
|
|
|
|
**Option Flags:**
|
|
|
|
Name Description
|
|
--------- ------------------------------------------
|
|
nocache Disables caching of the `{foreach}` loop
|
|
|
|
|
|
<?php
|
|
$arr = array('red', 'green', 'blue');
|
|
$smarty->assign('myColors', $arr);
|
|
?>
|
|
|
|
|
|
|
|
Template to output `$myColors` in an un-ordered list
|
|
|
|
|
|
<ul>
|
|
{foreach $myColors as $color}
|
|
<li>{$color}</li>
|
|
{/foreach}
|
|
</ul>
|
|
|
|
|
|
|
|
The above example will output:
|
|
|
|
|
|
<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);
|
|
?>
|
|
|
|
|
|
|
|
Template to output `$myArray` as key/value pairs.
|
|
|
|
|
|
<ul>
|
|
{foreach $myPeople as $value}
|
|
<li>{$value@key}: {$value}</li>
|
|
{/foreach}
|
|
</ul>
|
|
|
|
|
|
|
|
The above example will output:
|
|
|
|
|
|
<ul>
|
|
<li>fname: John</li>
|
|
<li>lname: Doe</li>
|
|
<li>email: j.doe@example.com</li>
|
|
</ul>
|
|
|
|
|
|
|
|
Assign an array to Smarty, the key contains the key for each looped
|
|
value.
|
|
|
|
|
|
<?php
|
|
$smarty->assign('contacts', array(
|
|
array('phone' => '555-555-1234',
|
|
'fax' => '555-555-5678',
|
|
'cell' => '555-555-0357'),
|
|
array('phone' => '800-555-4444',
|
|
'fax' => '800-555-3333',
|
|
'cell' => '800-555-2222')
|
|
));
|
|
?>
|
|
|
|
|
|
|
|
The template to output `$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}
|
|
|
|
|
|
|
|
Either of the above examples will output:
|
|
|
|
|
|
phone: 555-555-1234
|
|
fax: 555-555-5678
|
|
cell: 555-555-0357
|
|
phone: 800-555-4444
|
|
fax: 800-555-3333
|
|
cell: 800-555-2222
|
|
|
|
|
|
|
|
A database (PDO) example of looping over search results. This example is
|
|
looping over a PHP iterator instead of an array().
|
|
|
|
|
|
<?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}
|
|
|
|
|
|
|
|
The above is assuming the results contain the columns named `id` and
|
|
`name`.
|
|
|
|
What is the advantage of an iterator vs. looping over a plain old array?
|
|
With an array, all the results are accumulated into memory before being
|
|
looped. With an iterator, each result is loaded/released within the
|
|
loop. This saves processing time and memory, especially for very large
|
|
result sets.
|
|
|
|
\@index {#foreach.property.index}
|
|
-------
|
|
|
|
`index` contains the current array index, starting with zero.
|
|
|
|
|
|
{* 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 {#foreach.property.iteration}
|
|
-----------
|
|
|
|
`iteration` contains the current loop iteration and always starts at
|
|
one, unlike [`index`](#foreach.property.index). It is incremented by one
|
|
on each iteration.
|
|
|
|
The *\"is div by\"* operator can be used to detect a specific iteration.
|
|
Here we bold-face the name every 4th iteration.
|
|
|
|
|
|
{foreach $myNames as $name}
|
|
{if $name@iteration is div by 4}
|
|
<b>{$name}</b>
|
|
{/if}
|
|
{$name}
|
|
{/foreach}
|
|
|
|
The *\"is even by\"* and *\"is odd by\"* operators can be used to
|
|
alternate something every so many iterations. Choosing between even or
|
|
odd rotates which one starts. Here we switch the font color every 3rd
|
|
iteration.
|
|
|
|
|
|
{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}
|
|
|
|
|
|
|
|
This will output something similar to this:
|
|
|
|
|
|
<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.property.first}
|
|
-------
|
|
|
|
`first` is TRUE if the current `{foreach}` iteration is the initial one.
|
|
Here we display a table header row on the first iteration.
|
|
|
|
|
|
{* 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.property.last}
|
|
------
|
|
|
|
`last` is set to TRUE if the current `{foreach}` iteration is the final
|
|
one. Here we display a horizontal rule on the last iteration.
|
|
|
|
|
|
{* 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 {#foreach.property.show}
|
|
------
|
|
|
|
The show `show` property can be used after the execution of a
|
|
`{foreach}` loop to detect if data has been displayed or not. `show` is
|
|
a boolean value.
|
|
|
|
|
|
<ul>
|
|
{foreach $myArray as $name}
|
|
<li>{$name}</li>
|
|
{/foreach}
|
|
</ul>
|
|
{if $name@show} do something here if the array contained data {/if}
|
|
|
|
\@total {#foreach.property.total}
|
|
-------
|
|
|
|
`total` contains the number of iterations that this `{foreach}` will
|
|
loop. This can be used inside or after the `{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}
|
|
|
|
See also [`{section}`](#language.function.section),
|
|
[`{for}`](#language.function.for) and
|
|
[`{while}`](#language.function.while)
|
|
|
|
{break} {#foreach.construct.break}
|
|
-------
|
|
|
|
`{break}` aborts the iteration of the array
|
|
|
|
|
|
{$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} {#foreach.construct.continue}
|
|
----------
|
|
|
|
`{continue}` leaves the current iteration and begins with the next
|
|
iteration.
|
|
|
|
|
|
{$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
|
|
*}
|
|
|
|
|