Skip to content

Twig Conditionals

Complete guide to conditional statements in Total CMS Twig templates for controlling template flow based on dynamic data.

Conditional statements allow you to control the flow of your templates based on dynamic data. In Twig, you can use the {% if %} tag to test conditions and display content accordingly.

Basic syntax:

{% if condition %}
Content to display if true
{% endif %}

With else:

{% if condition %}
Content when true
{% else %}
Content when false
{% endif %}

With elseif:

{% if condition1 %}
Content for condition 1
{% elseif condition2 %}
Content for condition 2
{% else %}
Default content
{% endif %}

Tests if a variable has a “truthy” value. For booleans, it checks true/false. For variables, it returns false if undefined, null, empty string, empty array, or the number 0.

{% if post.draft %}
This post is a draft
{% endif %}

Inverts the condition - returns true when the value is false or falsy.

{% if not post.featured %}
This post is not featured
{% endif %}

Checks if a string value exactly matches another string.

{% if page.name == "home" %}
Welcome to the home page
{% endif %}

Explicitly compares a boolean value. Can use == true or == false.

{% if blog.featured == true %}
This is a featured post
{% endif %}

Compare numbers using operators: >, <, >=, <=, ==, !=

{% if product.inventory >= 10 %}
In stock
{% elseif product.inventory > 0 %}
Low stock
{% else %}
Out of stock
{% endif %}

Checks if values are not equal using != operator.

{% if user.role != "guest" %}
Welcome back, member!
{% endif %}

Check if a variable has been defined in the template context.

{% if myobject is defined %}
Object exists
{% endif %}
{% if myobject is not defined %}
Object does not exist
{% endif %}

Check if a variable is null (explicitly set to null, not just undefined).

{% if user.avatar is null %}
<img src="default-avatar.png">
{% else %}
<img src="{{ user.avatar }}">
{% endif %}

Tests if a variable is empty (empty string, empty array, or false).

{% if object.tags is empty %}
No tags available
{% else %}
{% for tag in object.tags %}
{{ tag }}
{% endfor %}
{% endif %}

Check if a file exists in your Total CMS file system.

{% if fileExists('documents/report.pdf') %}
<a href="documents/report.pdf">Download Report</a>
{% endif %}

Check if an image property exists for an object before attempting to display it.

{% if imageExists(post.image) %}
{{ cms.render.image(post.id, {collection: 'blog', property: 'image'}) }}
{% else %}
<img src="placeholder.jpg">
{% endif %}

Returns true if either condition is true. You can chain multiple OR conditions.

{% if user.role == "editor" or user.role == "admin" %}
You have editing permissions
{% endif %}

Returns true only if all conditions are true. You can chain multiple AND conditions.

{% if post.published == true and post.date < "now"|date %}
This post is live
{% endif %}

Use parentheses to group conditions and control evaluation order.

{% if (user.role == "admin" or user.role == "editor") and post.draft == false %}
Show edit button
{% endif %}

Check if a value exists within an array of values.

{% if post.category in ["news", "updates", "announcements"] %}
This is a news-related post
{% endif %}

Check if an array variable contains a specific value.

{% if "admin" in user.groups %}
Administrator access granted
{% endif %}

Check the number of items in an array using the length filter.

{% if post.tags|length > 0 %}
Tags: {{ post.tags|join(', ') }}
{% endif %}
{% if gallery.images|length >= 10 %}
This gallery has {{ gallery.images|length }} images
{% endif %}

Check if a collection has any objects before looping.

{% set posts = cms.collection.objects('blog') %}
{% if posts|length > 0 %}
{% for post in posts %}
{{ post.title }}
{% endfor %}
{% else %}
No blog posts found
{% endif %}

Check if a variable can be iterated over (arrays, objects, etc.).

{% if items is iterable %}
{% for item in items %}
{{ item }}
{% endfor %}
{% endif %}

Check if a string begins with a specific substring.

{% if product.sku starts with "PROD-" %}
Standard product
{% endif %}

Check if a string ends with a specific substring.

{% if user.email ends with "@example.com" %}
Internal user account
{% endif %}

Check if a string contains a substring. Use |lower for case-insensitive matching.

{% if "urgent" in post.title|lower %}
<span class="badge urgent">Urgent</span>
{% endif %}

Test if a string matches a regular expression pattern. Use double backslashes for escape sequences.

{% if user.phone matches '/^[\\d\\.\\-\\(\\)\\s]+$/' %}
Valid phone format
{% endif %}
{% if post.title matches '/\\d{4}/' %}
Title contains a year
{% endif %}

Compare a date field to the current date/time.

{% if event.date < "now"|date %}
This event has passed
{% endif %}

Compare a date to a specific date string.

{% if post.date > "2024-01-01"|date %}
Posted this year
{% endif %}

Check if a date falls within a specific range. Use modifiers like +7 days, -1 month, etc.

{% if event.date >= "now"|date and event.date <= "+7 days"|date %}
Happening this week
{% endif %}

Store dates in variables for cleaner comparisons.

{% set startDate = "2024-06-01"|date %}
{% set endDate = "2024-08-31"|date %}
{% if event.date >= startDate and event.date <= endDate %}
Summer event
{% endif %}

Check if an object exists before using it.

{% set page = cms.collection.object('pages', 'about') %}
{% if page %}
{{ page.content }}
{% else %}
Page not found
{% endif %}

Check a toggle’s state from your Total CMS settings.

{% if cms.toggle('maintenance-mode') %}
<div class="alert">Site under maintenance</div>
{% endif %}

Access and test configuration values.

{% if cms.config('debug') == true %}
Debug mode is enabled
{% endif %}

Check which environment the site is running in.

{% if cms.env == 'development' %}
<div class="debug-bar">Development Mode</div>
{% endif %}

Check if a user is logged in.

{% if cms.user %}
Welcome back, {{ cms.user.name }}!
{% else %}
<a href="/login">Login</a>
{% endif %}

Check if the logged-in user has specific roles or permissions.

{% if cms.user and "editor" in cms.user.roles %}
<a href="/admin/edit">Edit Content</a>
{% endif %}

Provide a default value if the variable is undefined or empty.

{% if product.rating|default(0) >= 4 %}
Highly rated!
{% endif %}

Test if a number is even or odd. Useful for alternating row styles.

{% for post in posts %}
<div class="{% if loop.index is even %}even{% else %}odd{% endif %}">
{{ post.title }}
</div>
{% endfor %}

Check if a number is divisible by another number. Great for grid layouts.

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

Check if two variables reference the exact same object (identity check, not equality).

{% if currentPage is same as(homePage) %}
<span class="active">Home</span>
{% endif %}

Check if a value matches a defined constant.

{% if status is constant('STATUS_ACTIVE') %}
Active status
{% endif %}

Inline conditional using the ternary operator condition ? true : false.

{{ post.featured ? 'Featured Post' : 'Regular Post' }}
{% set cssClass = post.published ? 'published' : 'draft' %}
<div class="{{ cssClass }}">{{ post.title }}</div>

Return the first defined value using the ?? operator. Similar to multiple |default filters.

{{ user.nickname ?? user.name ?? 'Guest' }}
{% set displayName = user.preferredName ?? user.firstName ?? user.username %}

Check if current iteration is the first item in the loop.

{% for post in posts %}
{% if loop.first %}
<div class="featured">{{ post.title }}</div>
{% else %}
<div class="regular">{{ post.title }}</div>
{% endif %}
{% endfor %}

Check if current iteration is the last item (useful for adding separators).

{% for item in items %}
{{ item.name }}{% if not loop.last %}, {% endif %}
{% endfor %}

Use loop.index (1-based) or loop.index0 (0-based) to check position.

{% for post in posts %}
{% if loop.index <= 3 %}
<div class="top-post">{{ post.title }}</div>
{% endif %}
{% endfor %}

Access the total number of items being looped through.

{% for post in posts %}
Post {{ loop.index }} of {{ loop.length }}
{% endfor %}

Always check if objects exist before accessing their properties to avoid errors:

{% set post = cms.collection.object('blog', 'my-post') %}
{% if post %}
{{ post.title }}
{% endif %}

Make complex conditions more readable by using variables:

{% set isAdmin = cms.user and "admin" in cms.user.roles %}
{% set isPublished = post.published and post.date <= "now"|date %}
{% if isAdmin or isPublished %}
{{ post.content }}
{% endif %}

For safety, combine existence and value checks:

{% if post.gallery is defined and post.gallery is not empty %}
{{ cms.render.gallery(post.id) }}
{% endif %}

Avoid calling CMS functions multiple times in conditions:

{# Bad - calls function multiple times #}
{% if cms.collection.objects('blog')|length > 0 %}
{{ cms.collection.objects('blog')|length }} posts
{% endif %}
{# Good - calls function once #}
{% set posts = cms.collection.objects('blog') %}
{% if posts|length > 0 %}
{{ posts|length }} posts
{% endif %}

Always check existence before accessing files or images:

{# Check if image exists #}
{% if imageExists(post.image) %}
{{ cms.render.image(post.id, {property: 'hero'}) }}
{% endif %}
{# Check if file exists #}
{% if fileExists('downloads/brochure.pdf') %}
<a href="downloads/brochure.pdf">Download</a>
{% endif %}
OperatorDescriptionExample
==Equal toprice == 10
!=Not equal tostatus != "draft"
<Less thanage < 18
>Greater thancount > 5
<=Less than or equalscore <= 100
>=Greater than or equalrating >= 4
OperatorDescriptionExample
andBoth conditions truepublished and featured
orEither condition trueadmin or editor
notNegate conditionnot deleted
()Group conditions(a or b) and c
TestDescriptionExample
definedVariable existsvar is defined
nullValue is nullvalue is null
emptyValue is emptyarray is empty
evenNumber is evennum is even
oddNumber is oddnum is odd
iterableCan be loopeditems is iterable
divisible byDivisible by numbernum is divisible by(3)
same asSame objecta is same as(b)
constantMatches constantx is constant('Y')
TestDescriptionExample
starts withString starts withstr starts with "hello"
ends withString ends withstr ends with ".com"
matchesMatches regexstr matches '/\\d+/'
inContains substring"test" in str
VariableDescriptionExample
loop.indexCurrent iteration (1-based){{ loop.index }}
loop.index0Current iteration (0-based){{ loop.index0 }}
loop.firstTrue if first iteration{% if loop.first %}
loop.lastTrue if last iteration{% if loop.last %}
loop.lengthTotal items in loop{{ loop.length }}
loop.parentParent loop context{{ loop.parent.index }}
{# Check nested properties safely #}
{% if user is defined and user.profile is defined and user.profile.avatar %}
{{ user.profile.avatar }}
{% endif %}
{# Or use default values #}
{{ user.profile.avatar|default('default.jpg') }}
{# Try multiple sources #}
{% set title = page.customTitle ?? page.title ?? 'Untitled' %}
{# Or with if statements #}
{% if page.customTitle %}
{{ page.customTitle }}
{% elseif page.title %}
{{ page.title }}
{% else %}
Untitled
{% endif %}
{# Single condition #}
<div class="post {{ post.featured ? 'featured' : '' }}">
{# Multiple conditions #}
<div class="post
{% if post.featured %}featured{% endif %}
{% if post.draft %}draft{% endif %}
{% if post.urgent %}urgent{% endif %}">
{# Complex logic #}
{% set statusClass = post.published ? 'published' : (post.draft ? 'draft' : 'pending') %}
<div class="post {{ statusClass }}">
{# Check user permissions #}
{% set canEdit = cms.user and (
"admin" in cms.user.roles or
"editor" in cms.user.roles or
cms.user.id == post.authorId
) %}
{% if canEdit %}
<a href="/edit/{{ post.id }}">Edit</a>
{% endif %}
{# Provide sensible defaults #}
{% set perPage = request.query.limit|default(10) %}
{% set sortBy = request.query.sort|default('date') %}
{% set order = request.query.order|default('desc') %}
{# Validate and constrain values #}
{% if perPage > 100 %}
{% set perPage = 100 %}
{% endif %}