Core dna renders server-side sites with Smarty or with Twig, one engine per site, and treats the two as peers. This guide is the one place both are documented: what they share, each engine's language and the platform's additions and limits, the two side by side, and translation.
L1–L2
Unit 03 · Twig
What the platform adds to Twig
TwigPage 17 of 25Updated
Stock Twig 3.19 plus the string extension, and the platform's own additions: debug_vars, four coercion filters that refuse null, an empty test that never calls a record empty, json_decode and its own set tag. What each one takes, the input that makes it fail, and the standard filters production Twig sites use most.
Who this is for. The developer on a Twig site who meets a filter or test that is not in the Twig manual, or one that behaves differently from it. Afterwards you can use each platform addition correctly, recognise its failure, and know which standard pieces are and are not installed.
The list
Name
Kind
Does
debug_vars
Function and filter
Shows the values passed in the debug panel, on development environments only
boolean, integer, float, string
Filters
Convert a value to that type, and fail on null
empty
Test
Replaces stock Twig's: a record is never empty
json_decode
Filter
Decodes a JSON string into arrays
u, slug
Filters
From the string extension: Unicode-safe string methods, and slugs
set
Tag
Replaces stock Twig's: also stores the value in _templateContext (The platform's set tag)
An unknown filter, function, test or tag is a compile error, so the whole template fails, not only the one expression.
debug_vars
Registered both as a function, {{ debug_vars(page, component) }}, and as a filter, {{ page|debug_vars }}. Either records the values you pass (not the whole scope) for the debug panel the platform adds before </body>, and prints nothing. It works only on a development environment; anywhere else it does nothing, so a forgotten one is harmless. It replaces dump(), which comes from Twig's debug extension and is not installed.
The coercion filters
Filter
Converts
Fails on
boolean
A string as PHP does ('' and '0' are false, 'false' is true); a number is true only when greater than 0; a boolean as it is
null, arrays
integer
A string as PHP's intval ('12px' is 12); a float rounded down (-1.5 is -2)
null, booleans, arrays
float
A string or integer as PHP's floatval
null, booleans, arrays
string
A number to its digits; an object to its string form
null, booleans, arrays
They exist to normalise area values, which arrive as text, before a comparison or arithmetic. They look like harmless casts and are not tolerant of a missing value: null makes the render fail with Cannot convert element of type NULL to integer. A blank area, or a variable that one include sets and another does not, is exactly that null. Supply the fallback first:
Template codeTwig only
{% set columns = component.getAreaText('columns')|integer %} {# fails when the area is blank #}
{% set columns = component.getAreaText('columns')|default(3)|integer %} {# safe #}
{% set wide = (settings.wide ?? false)|boolean %}
{% if component.getAreaText('layout') == 'true' %}…{% endif %} {# compare a word as text, not with |boolean #}
Two more things to know: |boolean calls the string 'false' true, so compare words as text; and |string on a record gives what printing it gives, which for most content records (a page, a post, a book, an FAQ entry, a product, a custom entity record, a form) is the whole rendered layout, for an image an <img> tag, and for other records the display name.
The empty test
The platform replaces is empty so that a record is never empty. Stock Twig decides whether an object is empty by turning it into a string, which for a page, a post or an image means rendering it, and a record whose string came out blank would count as empty. A missing record is null, and null is empty, so the test does what you mean:
Template codeTwig only
{% set author = post.getAreaRecord('author') %}
{% if author is not empty %}
<p class="byline">{{ author.getName()|e }}</p>
{% endif %}
{% if page.getChildren() is empty %}<p>No sub-pages.</p>{% endif %} {# a collection: empty at zero items #}
Beyond records, it is stock Twig's test: a collection or list is empty with no items, and otherwise '', false, null and [] are empty. 0 and '0' are not empty, unlike PHP's empty(), so a Number area set to zero counts as filled. Production Twig sites use is not empty more than any other platform addition.
json_decode
Decodes a JSON string, with objects as arrays, for the case where a small block of configuration is kept in a Text, Textarea or Code area:
Template codeTwig only
{% set raw = component.getAreaText('config') %}
{% set config = raw is not empty ? raw|json_decode : {} %}
<div class="grid grid--{{ config.columns ?? 3 }}"></div>
It fails rather than returning null: invalid JSON, a stray trailing comma included, makes the render fail with Syntax error, and the input must be a string, so null fails too. Hence the empty test first. An editor can break the page by saving bad JSON in that area, so keep such areas to developers, or validate the JSON before it is saved.
The string extension: u and slug
The u filter wraps a string so that you can call Unicode-safe methods on it; slug makes an ASCII slug.
Template codeTwig only
{{ title|u.truncate(60, '…') }} {# at most 60 characters, the ellipsis included #}
{{ title|u.truncate(60, '…', false) }} {# finishes the last word instead of cutting it #}
{{ title|u.wordwrap(30, '<br>', true) }}
{{ name|u.title(true) }} {# 'élan vital' becomes 'Élan Vital' #}
{{ title|slug|lower }} {# 'Our Services' becomes 'our-services' #}
slug keeps the case, so Our Services becomes Our-Services; add |lower for a URL, or pass a separator, |slug('_'). These are the only two filters the string extension adds.
Everything standard Twig provides
Every filter, function, test and tag in Twig's core works as the Twig 3 documentation describes, except where this page and Twig in Core dna say otherwise. The ones production Twig sites on Core dna use most:
Not installed, each a compile error: dump(), trans, the sandbox and cache tags, and the intl, html, markdown, inky and cssinliner extras, so no format_currency, format_datetime, html_classes or markdown_to_html. The core date and number_format filters cover most of what the intl extra would.