/documentation/en/designers/language-builtin-functions/language-function-foreach.xml
XML | 531 lines | 470 code | 40 blank | 21 comment | 0 complexity | 0c19ad488b692b124b85684ab6527263 MD5 | raw file
Possible License(s): LGPL-3.0
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- $Revision$ -->
- <sect1 id="language.function.foreach">
- <title>{foreach},{foreachelse}</title>
- <para>
- <varname>{foreach}</varname> is used for looping over arrays of data. <varname>{foreach}</varname> has a simpler and cleaner syntax than the <link linkend="language.function.section"><varname>{section}</varname></link> loop, and can also loop over associative arrays.
- </para>
- <para>
- <varname>{foreach $arrayvar as $itemvar}</varname>
- </para>
- <para>
- <varname>{foreach $arrayvar as $keyvar=>$itemvar}</varname>
- </para>
- <note>
- <para>
- This foreach syntax does not accept any named attributes. This syntax is new to Smarty 3, however the Smarty 2.x syntax <literal>{foreach from=$myarray key="mykey" item="myitem"}</literal> is still supported.
- </para>
- </note>
- <itemizedlist>
- <listitem><para>
- <varname>{foreach}</varname> loops can be nested.
- </para></listitem>
- <listitem><para>
- The <parameter>array</parameter> variable, usually an array of values,
- determines the number of times <varname>{foreach}</varname> will loop. You can also pass an integer for arbitrary loops.
- </para></listitem>
- <listitem><para>
- <varname>{foreachelse}</varname> is executed when there are no
- values in the <parameter>array</parameter> variable.
- </para></listitem>
-
- <listitem>
- <para>
- <varname>{foreach}</varname> properties are
- <link linkend="foreach.property.index"><parameter>@index</parameter></link>,
- <link linkend="foreach.property.iteration"><parameter>@iteration</parameter></link>,
- <link linkend="foreach.property.first"><parameter>@first</parameter></link>,
- <link linkend="foreach.property.last"><parameter>@last</parameter></link>,
- <link linkend="foreach.property.show"><parameter>@show</parameter></link>,
- <link linkend="foreach.property.total"><parameter>@total</parameter></link>.
- </para>
- </listitem>
-
- <listitem>
- <para>
- <varname>{foreach}</varname> constructs are
- <link linkend="foreach.construct.break"><varname>{break}</varname></link>,
- <link linkend="foreach.construct.continue"><varname>{continue}</varname></link>.
- </para>
- </listitem>
-
- <listitem><para>
- Instead of specifying the <parameter>key</parameter> variable you can access the current key of the
- loop item by <parameter>{$item@key}</parameter> (see examples below).
- </para></listitem>
-
- </itemizedlist>
-
- <note>
- <para>
- The <literal>$var@property</literal> syntax is new to Smarty 3, however when using the Smarty 2 <literal>{foreach from=$myarray key="mykey" item="myitem"}</literal> style syntax, the <literal>$smarty.foreach.name.property</literal> syntax is still supported.
- </para>
- </note>
- <note>
- <para>
- Although you can retrieve the array key with the syntax <literal>{foreach $myArray as $myKey => $myValue}</literal>, the key is always available as <varname>$myValue@key</varname> within the foreach loop.
- </para>
- </note>
-
-
- <para><emphasis role="bold">Option Flags:</emphasis></para>
- <informaltable frame="all">
- <tgroup cols="2">
- <colspec colname="param" align="center" />
- <colspec colname="desc" />
- <thead>
- <row>
- <entry>Name</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>nocache</entry>
- <entry>Disables caching of the <varname>{foreach}</varname> loop</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
-
- <example>
- <title>A simple <varname>{foreach}</varname> loop</title>
- <programlisting role="php">
- <![CDATA[
- <?php
- $arr = array('red', 'green', 'blue');
- $smarty->assign('myColors', $arr);
- ?>
- ]]>
- </programlisting>
- <para>Template to output <parameter>$myColors</parameter> in an un-ordered list</para>
- <programlisting>
- <![CDATA[
- <ul>
- {foreach $myColors as $color}
- <li>{$color}</li>
- {/foreach}
- </ul>
- ]]>
- </programlisting>
- <para>
- The above example will output:
- </para>
- <screen>
- <![CDATA[
- <ul>
- <li>red</li>
- <li>green</li>
- <li>blue</li>
- </ul>
- ]]>
- </screen>
- </example>
- <example>
- <title>Demonstrates the an additional <parameter>key</parameter> variable</title>
- <programlisting role="php">
- <![CDATA[
- <?php
- $people = array('fname' => 'John', 'lname' => 'Doe', 'email' => 'j.doe@example.com');
- $smarty->assign('myPeople', $people);
- ?>
- ]]>
- </programlisting>
- <para>Template to output <parameter>$myArray</parameter> as key/value pairs.</para>
- <programlisting>
- <![CDATA[
- <ul>
- {foreach $myPeople as $value}
- <li>{$value@key}: {$value}</li>
- {/foreach}
- </ul>
- ]]>
- </programlisting>
- <para>
- The above example will output:
- </para>
- <screen>
- <![CDATA[
- <ul>
- <li>fname: John</li>
- <li>lname: Doe</li>
- <li>email: j.doe@example.com</li>
- </ul>
- ]]>
- </screen>
- </example>
- <example>
- <title>{foreach} with nested <parameter>item</parameter> and <parameter>key</parameter></title>
- <para>Assign an array to Smarty, the key contains the key for each looped value.</para>
- <programlisting role="php">
- <![CDATA[
- <?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')
- ));
- ?>
- ]]>
- </programlisting>
- <para>The template to output <parameter>$contact</parameter>.</para>
- <programlisting>
- <![CDATA[
- {* 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}
- ]]>
- </programlisting>
- <para>
- Either of the above examples will output:
- </para>
- <screen>
- <![CDATA[
- phone: 555-555-1234
- fax: 555-555-5678
- cell: 555-555-0357
- phone: 800-555-4444
- fax: 800-555-3333
- cell: 800-555-2222
- ]]>
- </screen>
- </example>
- <example>
- <title>Database example with {foreachelse}</title>
- <para>A database (PDO) example of looping over search results. This example is looping over a PHP iterator instead of an array().</para>
- <programlisting role="php">
- <![CDATA[
- <?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');?>
- ?>
- ]]>
- </programlisting>
- <programlisting>
- <![CDATA[
- {foreach $res as $r}
- {$r.id}
- {$r.name}
- {foreachelse}
- .. no results ..
- {/foreach}
- ]]>
- </programlisting>
- </example>
- <para>
- The above is assuming the results contain the columns named <literal>id</literal> and <literal>name</literal>.
- </para>
- <para>
- 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.
- </para>
- <sect2 id="foreach.property.index">
- <title>@index</title>
- <para>
- <parameter>index</parameter> contains the current array index, starting with zero.
- </para>
- <example>
- <title><parameter>index</parameter> example</title>
- <programlisting>
- <![CDATA[
- {* 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>
- ]]>
- </programlisting>
- </example>
- </sect2>
- <sect2 id="foreach.property.iteration">
- <title>@iteration</title>
- <para>
- <parameter>iteration</parameter> contains the current loop iteration and always
- starts at one, unlike <link linkend="foreach.property.index"><parameter>index</parameter></link>.
- It is incremented by one on each iteration.
- </para>
- <example>
- <title><parameter>iteration</parameter> example: is div by</title>
- <para>
- The <emphasis>"is div by"</emphasis> operator can be used to detect a specific iteration. Here we bold-face the name every 4th iteration.
- </para>
- <programlisting>
- <![CDATA[
- {foreach $myNames as $name}
- {if $name@iteration is div by 4}
- <b>{$name}</b>
- {/if}
- {$name}
- {/foreach}
- ]]>
- </programlisting>
- </example>
- <example>
- <title><parameter>iteration</parameter> example: is even/odd by</title>
- <para>
- The <emphasis>"is even by"</emphasis> and <emphasis>"is odd by"</emphasis> 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.
- </para>
- <programlisting>
- <![CDATA[
- {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}
- ]]>
- </programlisting>
-
- <para>
- This will output something similar to this:
- </para>
- <screen>
- <![CDATA[
- <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>
- ...
- ]]>
- </screen>
-
- </example>
- </sect2>
- <sect2 id="foreach.property.first">
- <title>@first</title>
- <para>
- <parameter>first</parameter> is &true; if the current <varname>{foreach}</varname>
- iteration is the initial one. Here we display a table header row on the first iteration.
- </para>
- <example>
- <title><parameter>first</parameter> property example</title>
- <programlisting>
- <![CDATA[
- {* 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>
- ]]>
- </programlisting>
- </example>
- </sect2>
- <sect2 id="foreach.property.last">
- <title>@last</title>
- <para>
- <parameter>last</parameter> is set to &true; if the current
- <varname>{foreach}</varname> iteration is the final one. Here we display a horizontal rule on the last iteration.
- </para>
- <example>
- <title><parameter>last</parameter> property example</title>
- <programlisting>
- <![CDATA[
- {* 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}
- ]]>
- </programlisting>
- </example>
- </sect2>
- <sect2 id="foreach.property.show">
- <title>@show</title>
- <para>
- The show <parameter>show</parameter> property can be used after the execution of a
- <varname>{foreach}</varname> loop to detect if data has been displayed or not.
- <parameter>show</parameter> is a boolean value.
- </para>
- <example>
- <title><parameter>show</parameter> property example</title>
- <programlisting>
- <![CDATA[
- <ul>
- {foreach $myArray as $name}
- <li>{$name}</li>
- {/foreach}
- </ul>
- {if $name@show} do something here if the array contained data {/if}
- ]]>
- </programlisting>
- </example>
- </sect2>
- <sect2 id="foreach.property.total">
- <title>@total</title>
- <para>
- <parameter>total</parameter> contains the number of iterations that this
- <varname>{foreach}</varname> will loop.
- This can be used inside or after the <varname>{foreach}</varname>.
- </para>
- <example>
- <title><parameter>total</parameter> property example</title>
- <programlisting>
- <![CDATA[
- {* 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}
- ]]>
- </programlisting>
- </example>
- <para>
- See also <link linkend="language.function.section"><varname>{section}</varname></link>,
- <link linkend="language.function.for"><varname>{for}</varname></link>
- and
- <link linkend="language.function.while"><varname>{while}</varname></link>
- </para>
- </sect2>
-
- <sect2 id="foreach.construct.break">
- <title>{break}</title>
- <para>
- <varname>{break}</varname> aborts the iteration of the array
- </para>
- <example>
- <title><varname>{break}</varname> example</title>
- <programlisting>
- <![CDATA[
- {$data = [1,2,3,4,5]}
- {foreach $data as $value}
- {if $value == 3}
- {* abort iterating the array *}
- {break}
- {/if}
- {$value}
- {/foreach}
- {*
- prints: 1 2
- *}
- ]]>
- </programlisting>
- </example>
- </sect2>
-
- <sect2 id="foreach.construct.continue">
- <title>{continue}</title>
- <para>
- <varname>{continue}</varname> leaves the current iteration and begins with the next iteration.
- </para>
- <example>
- <title><varname>{continue}</varname> example</title>
- <programlisting>
- <![CDATA[
- {$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
- *}
- ]]>
- </programlisting>
- </example>
- </sect2>
-
- </sect1>
- <!-- Keep this comment at the end of the file
- Local variables:
- mode: sgml
- sgml-omittag:t
- sgml-shorttag:t
- sgml-minimize-attributes:nil
- sgml-always-quote-attributes:t
- sgml-indent-step:1
- sgml-indent-data:t
- indent-tabs-mode:nil
- sgml-parent-document:nil
- sgml-default-dtd-file:"../../../../manual.ced"
- sgml-exposed-tags:nil
- sgml-local-catalogs:nil
- sgml-local-ecat-files:nil
- End:
- vim600: syn=xml fen fdm=syntax fdl=2 si
- vim: et tw=78 syn=sgml
- vi: ts=1 sw=1
- -->