Skip to main content

Control Structures

Conditions (if)​

Conditions (if)
{% if user.isActive %}
<p>Welcome, {{ user.name }}!</p>
{% endif %}

elseif / else​

elseif / else
{% if user.role == 'admin' %}
<span class="badge bg-danger">Administrator</span>
{% elseif user.role == 'moderator' %}
<span class="badge bg-warning">Moderator</span>
{% elseif user.role == 'vip' %}
<span class="badge bg-success">VIP</span>
{% else %}
<span class="badge bg-secondary">User</span>
{% endif %}

Combining conditions​

Combining conditions
{% if user.isActive and user.age >= 18 %}
{# ... #}
{% endif %}

{% if not user.isBanned or user.role == 'admin' %}
{# ... #}
{% endif %}

{% if status in ['active', 'pending'] and count > 0 %}
{# ... #}
{% endif %}

Tests​

Tests
{# Is the variable defined #}
{% if user is defined %}

{# Is the variable empty #}
{% if items is not empty %}

{# Even/odd #}
{% if loop.index is even %}

{# Null check #}
{% if value is null %}

{# Type check #}
{% if data is iterable %}

Loop (for)​

Basic loop​

Basic loop
<ul>
{% for user in users %}
<li>{{ user.name }}</li>
{% endfor %}
</ul>

Iterating over keys and values​

Iterating over keys and values
{% for key, value in data %}
<dt>{{ key }}</dt>
<dd>{{ value }}</dd>
{% endfor %}

{# Iterating over keys only #}
{% for key in data|keys %}
{{ key }}
{% endfor %}

The loop variable​

Inside a for loop, the special loop variable is available:

VariableDescription
loop.indexCurrent iteration (starting from 1)
loop.index0Current iteration (starting from 0)
loop.revindexIterations until the end (starting from 1)
loop.revindex0Iterations until the end (starting from 0)
loop.firsttrue for the first iteration
loop.lasttrue for the last iteration
loop.lengthTotal number of iterations
loop.parentParent context (for nested loops)
The loop variable
{% for user in users %}
{{ loop.index }}. {{ user.name }}
{% if loop.first %} (first){% endif %}
{% if loop.last %} (last){% endif %}
{% if not loop.last %}, {% endif %}
{% endfor %}

Empty collections (else)​

Empty collections (else)
{% for article in articles %}
<article>
<h2>{{ article.title }}</h2>
</article>
{% else %}
<p>No articles found.</p>
{% endfor %}

Filtering in a loop​

Filtering in a loop
{# Iterate only over active users #}
{% for user in users if user.isActive %}
{{ user.name }}
{% endfor %}

{# Combined with else #}
{% for product in products if product.inStock %}
{{ product.name }}: ${{ product.price }}
{% else %}
<p>No products in stock.</p>
{% endfor %}

Range​

Range
{% for i in 0..9 %}
{{ i }}
{% endfor %}

{% for letter in 'a'..'f' %}
{{ letter }}
{% endfor %}

Assignment (set)​

Simple assignment​

Simple assignment
{% set name = 'World' %}
{% set price = 100 %}
{% set active = true %}
{% set items = ['a', 'b', 'c'] %}
{% set config = {debug: true, version: '1.0'} %}

Multiple assignment​

Multiple assignment
{% set foo, bar = 'hello', 'world' %}

Block assignment​

Block assignment
{% set content %}
<div class="card">
<h3>{{ title }}</h3>
<p>{{ description }}</p>
</div>
{% endset %}

{# Usage #}
{{ content }}

Execute without output (do)​

Evaluates an expression but does not output the result:

Execute without output (do)
{% do mw.someMethod() %}
{% do items.append('new item') %}

Variable scope (with)​

Limits the visibility of variables:

Variable scope (with)
{% with %}
{% set temp = 'This variable is not visible outside of with' %}
{{ temp }}
{% endwith %}
{# temp is not available here #}
Variable scope (with)
{# Passing specific variables #}
{% with {name: 'John', age: 30} only %}
{{ name }}, {{ age }}
{# Other context variables are not available here #}
{% endwith %}

Raw output (verbatim)​

Outputs content without Twig processing:

Raw output (verbatim)
{% verbatim %}
This text will not be processed: {{ var }} and {% if %}
Useful for documentation or client-side templates (Vue.js, Angular)
{% endverbatim %}

Applying filters to a block (apply)​

Applying filters to a block (apply)
{% apply upper %}
This text will be in uppercase
{% endapply %}

{% apply spaceless %}
<div>
<strong>text</strong>
</div>
{% endapply %}
{# Result: <div><strong>text</strong></div> #}

{# Filter chain #}
{% apply lower|escape %}
<SOME> HTML & TEXT
{% endapply %}

Escaping control (autoescape)​

Escaping control (autoescape)
{# Enable auto-escaping #}
{% autoescape %}
{{ user_input }} {# Will be escaped #}
{% endautoescape %}

{# Specify strategy #}
{% autoescape 'html' %}
{{ content }}
{% endautoescape %}

{% autoescape 'js' %}
var data = {{ json_data }};
{% endautoescape %}

{# Disable auto-escaping #}
{% autoescape false %}
{{ trusted_html }}
{% endautoescape %}
caution

Disabling autoescape is only acceptable for trusted content. Never disable escaping for user input.