Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine

The for "loop" and inline "if" Syntax

Keep on Learning!

If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.

Start your All-Access Pass
Buy just this tutorial for $12.00

Let's give ourselves a challenge! Our products are printing out a bit weird right now because they're floating but not breaking correctly. To fix this, we need to wrap every three products in their very own row div.

To do this, we can use a divisible by() test to see if the item number we're on is divisible by three:

<div class="row">
    {% for product in products %}
        <div class="span4">
            {# ... #}
        </div>

        {% if loopNumber is divisible by(3) %}
            </div><div class="row">
        {% endif %}
    {% endfor %}
</div>

Just like functions and filters, sometimes a "test" also takes one or more arguments.

When we refresh, Twig is sad because the loopNumber variable is undefined. Yep, that's totally my fault, I made up that variable out of thin air. So how can we figure out how many items into the loop we are?

The Magical loop Variable

Twig comes to the rescue here and lets us say loop.index.

{% for product in products %}
    {# ... #}

    {% if loop.index is divisible by(3) %}
        </div><div class="row">
    {% endif %}
{% endfor %}

When we refresh, things work awesomely! So where did this magical loop variable come from? Normally in Twig, we have access to a few variables that were passed to us and that's it. If we use an undefined variable, we see an error.

This is all 100% true. But when we're inside a for tag, we magically have access to a new variable called loop. loop.first and loop.last tell us if this is the first or last item in the collection while loop.index counts up 1, 2, 3, 4 and so on for each item. Twig has a lot of really slick features like this, which you can find out by reading further into its docs.

In fact, to avoid an extra row being added if we have exactly 3, 6 or 9 objects, let's not print a new row if we're on the last item:

{% for product in products %}
    {# ... #}

    {% if loop.index is divisible by(3) and not loop.last %}
        </div><div class="row">
    {% endif %}
{% endfor %}

And not that it matters for Twig, but let's also move our "even" products message into its own row where it belongs.

{# templates/homepage.twig #}
{# ... after the for loop #}

{% if products|length is even %}
    <div class="row">
        <div class="span12">
            There is an even number of products! OMG!
        </div>
    </div>
{% endif %}

When we refresh, everything looks good and clean!

The for-else tag

While we're talking about cool for loop features, let's see another one: the for-else trick. Instead of seeing if products is empty, we can add an else tag inside of the for loop.

{% for product in products %}
    {# ... #}
{% else %}
    <div class="alert alert-error span12">
        It looks like we're out of really awesome-looking penguin clothes :/.
    </div>
{% endfor %}

If products is empty, it skips the for loop and calls the else section instead. When we try it, it still works great.

The inline if Syntax

Finally, let's see a really short syntax you can choose to use instead of the classic if tag. Head back to the banner template where we're setting the backgroundColor variable if it's not set and then printing it. Let's remove all of this and instead put all the logic in the "say something" block:

<div class="well" style="background-color: {{ backgroundColor is defined ? backgroundColor : 'lightBlue' }};">
    {# ... #}
</div>

You may be familiar with this syntax from another language, but if you're not, don't worry! It looks odd, but is really easy. The first part is a condition that returns true or false, just like an if statement. If it's true, the first variable backgroundColor is printed. If it's false, the second string lightblue is printed. The result is identical to before.

Leave a comment!

9
Login or Register to join the conversation
Victor Avatar Victor | SFCASTS | posted 5 years ago | edited

We could also to use <a href="http://twig.sensiolabs.org/doc/filters/default.html&quot;&gt;default&lt;/a&gt; filter instead of is defined test, for example:


{{ backgroundColor | default('lightBlue') }}

This is more readable and elegant solution, imo.

1 Reply

You're absolutely right :) - I like using default like this too.

Reply
Beniamin T. Avatar
Beniamin T. Avatar Beniamin T. | posted 4 years ago | edited

Hello beautiful people. I wonder why in the if statement that is just before the for loop we put the closing div tag before the div open tag class row. Thanks for your answers.
`
{% if loop.index is divisibleby(3) %}

            </div><div class="row">
        {% endif %}

`

Reply

Hey Beniamin T.

That's because we have to close the first "row" element before adding another row element into the layout. But it looks weird, I know :)

Cheers!

Reply
Default user avatar
Default user avatar Dylan Delobel ☕ | posted 5 years ago

Why divisible by over batch filter ?

Reply

Hey Dylan Delobel ☕!

Great question :). And I don't have a good reason - the batch filter is great! Actually, when we created this tutorial, the batch filter either didn't exist or was quite new. So, it's an excellent tool.

Cheers!

Reply
Default user avatar

Is the syntax of the "divisible by" test `divisible by` or `divisibleby` ?
(i.e. does it matter if there is a space between the words?)

The dox and the example don't match...

Reply

Hey Goz,

Yes, it does matter! Well, depends on Twig version. In Twig 2.x only "divisible by()" works, but in 1.x both syntax were allowed, but "divisible by()" were added as an alias since 1.14.2. See related docs:
https://twig.symfony.com/do...
https://twig.symfony.com/do...

Cheers!

Reply
Default user avatar

Got it - thanks!

Reply
Cat in space

"Houston: no signs of life"
Start the conversation!

This tutorial uses Twig 1. There are newer versions of Twig, but they don't contain significant differences. So, Twig on!

What PHP libraries does this tutorial use?

// composer.json
{
    "require": []
}
userVoice