The {foreach} statements allow you to loop through an array of data and render the results in a message. They are used in conjunction with "get" methods that return data arrays to be looped through.
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 color names and render them in the message.
Below is the code we'll be working with. The tabs display the HTML/ Smarty, the resulting HTML, and the rendered output.
-
{$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 a message and previewing it. The preview will run the Smarty functions and show you the rendered output.
Code breakdown
-
First we'll set a variable with the value being an array of colors. Normally you'll access data arrays with a "get" method, but for this example we'll place the data array in the message.
{$colors = ['red','blue','green','purple']}
The example above sets a variable called "colors" for the array of colors.
-
Then we'll set a variable for each item in the array and start the {foreach} loop.
{foreach $colors as $color}
The example above sets a variable called "color" for each item in the array.
-
Next we'll write HTML that will render each item followed by a line break.
{$color}<br>
-
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 is 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 that was set within the message code. Now let's take an example of an array of data that is stored as a supplement.
We've created a supplement called "Automobiles" with a key name of "automobiles" and have included the following fields:
- Model
- Brand
- Price
- Mileage
Download the sample data in CSV format and use the API to upload into your system for testing.
Here is an example of the HTML/Smarty, the supplement data (in JSON format) and the how the rendered output will look.
-
{$cars=$utils->getSupplementRecords('automobiles')} {foreach $cars as $car} <strong>{$car.brand} {$car.model}</strongbr> ${$car.price}<br> Mileage: {$car.mileage}<br><br> {/foreach}
-
[ { "model": "Pilot", "brand": "Honda", "price": 33000, "mileage": 100000, "id": "01" }, { "model": "Explorer", "brand": "Ford", "price": 34000, "mileage": 39000, "id": "02" }, { "model": "Prius", "brand": "Toyota", "price": 27000, "mileage": 66000, "id": "03" }, { "model": "Model S", "brand": "Tesla", "price": 130000, "mileage": 56000, "id": "04" }, { "model": "Versa", "brand": "Nissan", "price": 16000, "mileage": 94000, "id": "05" }, { "model": "Camary", "brand": "Toyota", "price": 29000, "mileage": 310000, "id": "06" }, { "model": "Accord", "brand": "Honda", "price": 24000, "mileage": 49000, "id": "07" } ]
-
Honda Pilot
$33000
Mileage: 100000
Ford Explorer
$34000
Mileage: 39000
Toyota Prius
$27000
Mileage: 66000
Tesla Model S
$130000
Mileage: 56000
Nissan Versa
$16000
Mileage: 94000
Toyota Camary
$29000
Mileage: 310000
Honda Accord
$24000
Mileage: 49000
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.
{$cars=$utils->getSupplementRecords('automobiles')}
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 "car".
{foreach $cars as $car}
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>{$car.brand} {$car.model}</strong><br>
${$car.price}<br>
Mileage: {$car.mileage}<br><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 cars with less than 60,000 miles.
-
{$cars=$utils->getSupplementRecords('automobiles')} {foreach $cars as $car} {if $car.mileage < 50000} <strong>{$car.brand} {$car.model}</strong><br> ${$car.price}<br> Mileage: {$car.mileage}<br><br> {/if} {/foreach}
-
[ { "model": "Pilot", "brand": "Honda", "price": 33000, "mileage": 100000, "id": "01" }, { "model": "Explorer", "brand": "Ford", "price": 34000, "mileage": 39000, "id": "02" }, { "model": "Prius", "brand": "Toyota", "price": 27000, "mileage": 66000, "id": "03" }, { "model": "Model S", "brand": "Tesla", "price": 130000, "mileage": 56000, "id": "04" }, { "model": "Versa", "brand": "Nissan", "price": 16000, "mileage": 94000, "id": "05" }, { "model": "Camary", "brand": "Toyota", "price": 29000, "mileage": 310000, "id": "06" }, { "model": "Accord", "brand": "Honda", "price": 24000, "mileage": 49000, "id": "07" } ]
-
Ford Explorer
$34000
Mileage: 39000
Honda Accord
$24000
Mileage: 49000
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.
-
{$cars=$utils->getSupplementRecords('automobiles')} {$counter = 0} {foreach $cars as $car} {if $counter > 3 }{break}{/if} <strong>{$car.brand} {$car.model}</strong><br> ${$car.price}<br> Mileage: {$car.mileage}<br><br> {$counter = $counter+1} {/foreach}
-
[ { "model": "Pilot", "brand": "Honda", "price": 33000, "mileage": 100000, "id": "01" }, { "model": "Explorer", "brand": "Ford", "price": 34000, "mileage": 39000, "id": "02" }, { "model": "Prius", "brand": "Toyota", "price": 27000, "mileage": 66000, "id": "03" }, { "model": "Model S", "brand": "Tesla", "price": 130000, "mileage": 56000, "id": "04" }, { "model": "Versa", "brand": "Nissan", "price": 16000, "mileage": 94000, "id": "05" }, { "model": "Camary", "brand": "Toyota", "price": 29000, "mileage": 310000, "id": "06" }, { "model": "Accord", "brand": "Honda", "price": 24000, "mileage": 49000, "id": "07" } ]
-
Honda Pilot
$33000
Mileage: 100000
Ford Explorer
$34000
Mileage: 39000
Toyota Prius
$27000
Mileage: 66000
Tesla Model S
$130000
Mileage: 56000
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.
-
{$cars=$utils->getSupplementRecords('automobiles')}
{foreach $cars as $car}
{if $car@iteration > 3 }{break}{/if}
<strong>{$car.brand} {$car.model}</strong><br>
${$car.price}<br>
Mileage: {$car.mileage}<br><br>
{/foreach} -
[ { "model": "Pilot", "brand": "Honda", "price": 33000, "mileage": 100000, "id": "01" }, { "model": "Explorer", "brand": "Ford", "price": 34000, "mileage": 39000, "id": "02" }, { "model": "Prius", "brand": "Toyota", "price": 27000, "mileage": 66000, "id": "03" }, { "model": "Model S", "brand": "Tesla", "price": 130000, "mileage": 56000, "id": "04" }, { "model": "Versa", "brand": "Nissan", "price": 16000, "mileage": 94000, "id": "05" }, { "model": "Camary", "brand": "Toyota", "price": 29000, "mileage": 310000, "id": "06" }, { "model": "Accord", "brand": "Honda", "price": 24000, "mileage": 49000, "id": "07" } ]
-
Honda Pilot
$33000
Mileage: 100000
Ford Explorer
$34000
Mileage: 39000
Toyota Prius
$27000
Mileage: 66000
Tesla Model S
$130000
Mileage: 56000
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 = ["brand"=>"toyota", "price"=>"30000", "junk"=>["foo"=>"bar", "biz"=>"baz"]]} {$include_array = ["brand", "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
{ "brand": "toyota", "price": "30000" }
Debug Big Object{ "brand": "toyota", "price": "30000", "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.