Lesson 2.3: Loops with foreach
Most pages show lists: the articles of a folder, the items of a menu, the images of a gallery. {foreach} is the
loop of the template language. In this lesson learners loop over arrays, hashes and the children of a node, and
use the parts of foreach that save extra code: delimiters, sequences, offset and max.
At a glance
| Course | Developers |
| Module | Module 2: The template language |
| Duration | 45 minutes (15 presenting, 30 exercise) |
| Level | Beginner |
| Audience | Developers and template builders |
| Prerequisites | Lesson 2.2 |
Learning objectives
After this lesson, learners can:
- loop over an array or a hash with
{foreach $list as $item}and{foreach $hash as $key => $value}; - put separators between items with
{delimiter}; - alternate CSS classes with
sequence ... as $class; - limit and reorder a loop with
offset,maxandreverse; - leave or skip with
{break},{continue}and{skip}, and count with|count.
Trainer's notes
How to present it
Source: the syntax comment in lib/eztemplate/classes/eztemplateforeachfunction.php:
{foreach <array> as [$keyVar =>] $itemVar
[sequence <array> as $sequenceVar]
[offset <offset>]
[max <max>]
[reverse]}
[delimiter.../delimiter]
[break] [continue] [skip]
/foreach- The plain loop (3 minutes).
{foreach $list as $item}{$item}{/foreach}. Show it over an array and over$node.children, an attribute of the node that returns its child nodes. - Keys (2 minutes).
{foreach $hash as $key => $value}gives the key too; for an array the key is the index, counted from 0. - Delimiter (2 minutes).
{delimiter}, {/delimiter}is printed between items, never after the last. - Sequence (3 minutes).
sequence array( 'odd', 'even' ) as $classcycles through the values, for zebra rows. - Offset, max, reverse (3 minutes). Skip the first items, stop after a number, go backwards.
- Leaving early (2 minutes).
{break}ends the loop,{continue}and{skip}go to the next item.
Common questions
Should I loop over $node.children on a large folder? No. It loads every child. For real lists use
fetch( 'content', 'list', ... ) with a limit (module 5); $node.children is fine for a few items.
Is there a counter? Use the key of an array loop, or {set $i = $i|inc} inside the loop with a variable
declared before it.
What about {section}? It is the older loop, still found in old templates. Write new templates with
foreach.
Pitfalls
- Washing inside loops. Every printed name still needs
|wash. definside a loop. A{def}inside the loop runs on every item and warns from the second time. Declare before the loop,setinside.- Large loops in the playground. On a big folder, keep
maxsmall so the output stays readable.
Hands-on exercise
Use the playground from lesson 2.1 (extension/mysite_hello/scripts/play.tpl), running
php bin/php/ezexec.php extension/mysite_hello/scripts/play.php after each step.
Loop over an array with its keys and a delimiter:
def $colors = array( 'red', 'green', 'blue' ) foreach $colors as $i => $color$i:$colordelimiter, /delimiter/foreachAdd alternating classes:
<ul> foreach $colors as $color sequence array( 'odd', 'even' ) as $class <li class="$class">$color|wash</li> /foreach </ul>Show only the second and third item:
{foreach $colors as $c max 2 offset 1}{$c} {/foreach}.Show them backwards:
{foreach $colors as $c reverse}{$c} {/foreach}.Count them:
{$colors|count} colors.Loop over the children of the node, at most five:
<ul> foreach $node.children as $child max 5 <li>$child.name|wash ($child.class_identifier)</li> /foreach </ul>Skip hidden children: add
{if $child.is_hidden}{continue}{/if}as the first line inside the loop.Loop over a hash:
{foreach hash( 'a', 1, 'b', 2 ) as $key => $value}{$key}={$value} {/foreach}.Free the variables at the end with
{undef $colors}and commit the template.
Expected result
- Step 1 prints
0:red, 1:green, 2:blue. - Step 2 prints three
<li>elements with the classesodd,even,odd. - Step 3 prints
green blue; step 4blue green red; step 53 colors. - Step 6 prints the names and class identifiers of up to five children of node 2.
- Step 8 prints
a=1 b=2. - The trainer checks the output of step 6 against the content tree in the administration.
Quiz
- How do you print
,between items but not after the last one? - Which part of
foreachalternates CSS classes? A.delimiterB.sequenceC.offsetD.reverse - What does
{foreach $list as $c max 2 offset 1}print forarray( 'a', 'b', 'c', 'd' )? - Why is
$node.childrena poor choice for a folder with thousands of items? - What is the difference between
{break}and{continue}?
Answers
- With
{delimiter}, {/delimiter}inside the loop. - B.
sequence array( 'odd', 'even' ) as $class. bandc: skip one, then take two.- It loads every child; a
fetchwith alimitloads one page (module 5). {break}ends the loop;{continue}goes on with the next item.
Further reading
- Templates and design, part 6: the language in ten minutes, with a complete list template.
- String template operators: operators to use on the items.
Related pages
- Module 2: The template language
- Developers: course overview
- Trainers: start here
- Free documentation: this page is free to copy, translate and improve under the GNU FDL 1.3.
Become an Exponential Partner
Partners share their information, provide funding, contribute back and develop the products with us, and that is how Exponential grows. A partner website and dashboard are planned for mid-2027: please become a partner today to speed up our growth rate and land new features faster.