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:
| Variable | Description |
|---|---|
loop.index | Current iteration (starting from 1) |
loop.index0 | Current iteration (starting from 0) |
loop.revindex | Iterations until the end (starting from 1) |
loop.revindex0 | Iterations until the end (starting from 0) |
loop.first | true for the first iteration |
loop.last | true for the last iteration |
loop.length | Total number of iterations |
loop.parent | Parent 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.