Overview
{foreach}
statements allow you to loop through an array of data and render the results in a message. They're commonly used to display similar and related products after someone browses or purchases an item, or puts a product in their cart. {foreach}
statements are used in conjunction with GET methods that return data arrays.
The following properties and constructs are supported for use with {foreach}
:
- Properties:
@index
,@iteration
,@first
,@last
,@show
,@total
- Constructs:
{break}
,{continue}
Loop through a simple array
Our first example demonstrates how to loop through an array of product color names and render them in the message. Below is the code we'll build upon.
-
{$colors = ['red','blue','green','purple']} {foreach $colors as $color} {$color}<br> {/foreach}
-
red<br> blue<br> green<br> purple<br>
-
red
blue
green
purple
You can test this code yourself by pasting it into your message HTML or Sculpt Block and previewing it. The preview will run the Smarty functions and show you the rendered output.
Code breakdown
1. First we'll set a variable with the value being an array of product colors. Normally you'd access data arrays with a GET method, but for this example we'll place the data array in the message. The example below sets a variable called colors
for the array of colors.
{$colors = ['red','blue','green','purple']}
2. Then we'll set a variable for each item in the array and start the {foreach}
loop. The example below sets a variable called color
for each item in the array.
{foreach $colors as $color}
3. Next we'll write HTML that will render each item followed by a line break.
{$color}<br>
4. Finally, we'll close the {foreach}
{/foreach}
Render loop in a bulleted list
If we want to render the colors as a bulleted list, we can add some additional HTML. Notice how we'll place the opening and closing <ul>
tags outside of the {foreach}
statement. The <li>
and </li>
tags are placed inside of the {foreach}
because that 's the code we want to render for every loop.
-
{$colors = ['red','blue','green','purple']} <ul> {foreach $colors as $color} <li>{$color}</li> {/foreach} </ul>
-
<ul> <li>red</li> <li>blue</li> <li>green</li> <li>purple</li> </ul>
-
- red
- blue
- green
- purple
Render loop in a table
Let's extend the example by placing the data inside a table. Notice how we place the <table>
tag outside of the {foreach}
. The <tr>
and <td>
tags are inside the {foreach}
because that is the code we want to render for every loop.
-
{$colors = ['red','blue','green','purple']} <table> {foreach $colors as $color} <tr> <td>{$color}</td> </tr> {/foreach} </table>
-
<table> <tr> <td>red</td> </tr> <tr> <td>blue</td> </tr> <tr> <td>green</td> </tr> <tr> <td>purple</td> </tr> </table>
-
red blue green purple
Loop through supplement data
In the previous examples we looped through an array of data set within the message code. Now let's take an example of an array of data that's stored as a supplement. This tactic could be used to display similar or related products to someone's browsing behavior or cart activity.
We've created a supplement called pants
and have included the following fields:
- Item
- Seasonal collection
- Price
You can put the sample data in CSV format and use the API to upload into your system for testing.
Here's an example of the HTML & Smarty, the supplement data in JSON format, and how the rendered output will look.
-
{$clothing=$utils->getSupplementRecords('pants')} {foreach $pants as $pants} <strong>{$pants.collection} {$pants.item}</strongbr> ${$pants.price}<br> {/foreach}
-
[ { "model": "joggers", "collection": "spring", "price": 75, "id": "01" }, { "model": "sweatpants", "collection": "winter", "price": 60, "id": "02" }, { "model": "rise_jeans", "collection": "fall", "price": 100, "id": "03" }, { "model": "capris", "collection": "spring", "price": 85, "id": "04" }, { "model": "cargos", "collection": "fall", "price": 100, "id": "05" }, { "model": "old_school", "collection": "fall", "price": 95, "id": "06" } ]
-
Joggers
$75
Spring collection
Sweatpants
$60
Winter collection
Rise Jeans
$100
Fall collection
Capris
$85
Spring collection
Cargos
$100
Fall collection
Old School
$95
Fall collection
Code breakdown
In order to render this data in a message, we need to make it available by using a GET method. For supplement data we use the getSupplementRecords method.
{$clothing=$utils->getSupplementRecords('pants')}
Next we'll set a variable for each record in the array and start the {foreach}
loop. We can use any name, but for this example we'll use the name clothing
.
{foreach $clothing as $pants}
Now we can reference each of the variables in the array. We'll write the HTML and the Smarty variables we want to render for each loop. The loop will run until there are no more records left in the array.
<strong>{$pants.collection} {$pants.item}</strong><br>
${$pants.price}<br>
{/foreach}
Note that each variable is prepended with the name of the variable we set in the {foreach}
statement.
Limit the number of records using an {if}
statement
Let's extend the previous example and add an {if}
condition to render a filtered result that only shows pants that cost less than $90.
-
{$clothing=$utils->getSupplementRecords('pants')} {foreach $clothing as $pants} {if $pants.price < 90} <strong>{$pants.item} {$pants.collection}</strong><br> ${$pants.price}<br> {/if} {/foreach}
-
[ { "model": "joggers", "collection": "spring", "price": 75, "id": "01" }, { "model": "sweatpants", "collection": "winter", "price": 60, "id": "02" }, { "model": "rise_jeans", "collection": "fall", "price": 100, "id": "03" }, { "model": "capris", "collection": "spring", "price": 85, "id": "04" }, { "model": "cargos", "collection": "fall", "price": 100, "id": "05" }, { "model": "old_school", "collection": "fall", "price": 95, "id": "06" } ]
-
Joggers
$75
Spring collection
Sweatpants
$60
Winter collection
Capris
$85
Spring collection
Limit the number of records using a counter and {break}
By starting a counter and incrementing the number for each loop, we can limit the amount of records by setting a {break}
if the counter reaches 4.
-
{$clothing=$utils->getSupplementRecords('pants')} {$counter = 0}
{foreach $clothing as $pants}
{if $counter > 3 }{break}{/if} {if $pants.price < 90} <strong>{$pants.item} {$pants.collection}</strong><br> ${$pants.price}<br> {$counter = $counter+1} {/foreach} -
[ { "model": "joggers", "collection": "spring", "price": 75, "id": "01" }, { "model": "sweatpants", "collection": "winter", "price": 60, "id": "02" }, { "model": "rise_jeans", "collection": "fall", "price": 100, "id": "03" }, { "model": "capris", "collection": "spring", "price": 85, "id": "04" }, { "model": "cargos", "collection": "fall", "price": 100, "id": "05" }, { "model": "old_school", "collection": "fall", "price": 95, "id": "06" } ]
-
Joggers
$75
Spring collection
Sweatpants
$60
Winter collection
Rise Jeans
$100
Fall collection
Capris
$85
Spring collection
Limit the number of records using @iteration
and {break}
Smarty has a built in counter that will count each loop as an iteration. We can use @iteration
to {break}
out of the loop when it reaches 4.
-
{$clothing=$utils->getSupplementRecords('pants')}
{foreach $clothing as $pants}
{if $pants@iteration > 3 }{break}{/if}
<strong>{$pants.item} {$pants.collection}</strong><br>
${$pants.price}<br>
{/foreach} -
[ { "model": "joggers", "collection": "spring", "price": 75, "id": "01" }, { "model": "sweatpants", "collection": "winter", "price": 60, "id": "02" }, { "model": "rise_jeans", "collection": "fall", "price": 100, "id": "03" }, { "model": "capris", "collection": "spring", "price": 85, "id": "04" }, { "model": "cargos", "collection": "fall", "price": 100, "id": "05" }, { "model": "old_school", "collection": "fall", "price": 95, "id": "06" } ]
-
Joggers
$75
Spring collection
Sweatpants
$60
Winter collection
Rise Jeans
$100
Fall collection
Capris
$85
Spring collection
Use {continue}
to omit an iteration and continue with the next
You can skip specific iterations and {continue}
looping through the remaining iterations that match your query.
-
{$contains.lookup_str = 'berry'} {$contains.caseSensitive = false} {$data.fruits = ["apple", "orange", "banana", "kiwi", "strawberry", "watermelon", "pear", "blackberry", "blueberry"]} {foreach $data.fruits as $berry} {$contains.string = $berry} {if $utils->strContains($contains.lookup_str, $contains.string, $contains.caseSensitive)} {$berry}<br> {else} {continue} {* not a berry, skip this loop, but do not break.*} {/if} {/foreach}
- strawberry
blackberry
blueberry
Use both the key and the value
In some use cases it is nice to have access to both the key and the value.
-
{$big_object = ["item"=>"cargos", "price"=>"100", "junk"=>["foo"=>"bar", "biz"=>"baz"]]} {$include_array = ["item", "price"]} {foreach $big_object as $key => $value} {if in_array($key, $include_array)} {$small_object[$key] = $value} {/if} {/foreach} <h2>Debug Small Object</h2> <pre>{json_encode($small_object, 128)}</pre> <h2>Debug Big Object</h2> <pre>{json_encode($big_object, 128)}</pre>
-
Debug Small Object
{ "item": "cargos", "price": "100" }
Debug Big Object{ "item": "cargos", "price": "100", "junk": { "foo": "bar", "biz": "baz" } }
Use a {for}
loop
In some use cases, it's useful to loop through a known number of iterations.
-
{$from = 0} {$to = 2}
{for $i=$from to $to} i is: {$i}<br> {/for} -
i is: 0 i is: 1 i is: 2
Comments
0 comments
Please sign in to leave a comment.