How to check for
undefined variables

Everyone working with Twig templates has experienced an undefined error
=> Error: Variable 'blah' does not exist.

This error means you’re trying to access a variable in your code that hasn’t been set.

There’s different ways in Twig to check for undefined variables so let’s get stuck in!

Is defined

Starting with the most obvious choice. is defined checks if the variable is defined and nothing more.

{# Check a variable is defined #}
{% if twigVariable is defined %}
    The value could be:
    0, false, null, [], {} or ''
{% else %}
    Value is not defined
{% endif %}

{# Check a field is defined within an iterable #}
{% if twigVariable['fieldName'] is defined %}
...

‘default filter’ with empty fallback

The default filter is commonly used to display a fallback value within the brackets if the attached variable is undefined.

Eg: twigVariable|default('this is the fallback')

🔥 What the twig documentation doesn’t mention is that the filter fallback value can be empty.

  • It’s ideal for checking if anything is empty, false or undefined
  • It reads as null which means you can guard against undefined errors like this:
{# Check a variable with an empty default filter #}
{% if twigVariable|default %}
    Value is set and not empty
{% else %}
    Value is either undefined, false, 0, null, "", [] or {}
{% endif %}

{# or check a field within an iterable #}
{% if twigVariable['fieldName']|default %}
...

Sometimes it’s clearer to use ternary syntax and the default filter works well here too:

{# Check a variable with ternary default filter #}
{{ twigVariable|default
    ? 'Value is set and not empty'
    : 'Value is undefined, false, 0, null, "", [] or {}'
}}

{# or check a field within an iterable #}
{{ twigVariable['fieldName']|default ? 'set' : 'unset' }}

The default filter has the same checks as is defined combined with is not empty:

{# |default checks for the same things as: #}
{{ twigVariable is defined
    and twigVariable is not empty ? 'set' : 'unset' }}

‘default filter’ with specified fallback

This is perfect for showing a value on screen with a fallback and with a minimal amount of code:

{{ twigVariable|default('twigVariable is not defined') }}
{# Checks value for undefined, false, null, "", [] or {}' #}

❗ But there’s an important difference compared to an empty default filter:

If twigVariable is set as 0 you won’t receive a fallback and it will return an empty string instead.

Null coalescing operator

Let’s geek it up a notch 🤓 and learn about this rarely used but powerful operator.

The ?? operator is similar to is defined but has some handy additions.

You can quickly specify fallbacks if your variable is undefined. It looks like this:

{# Check a variable with the null coalescing operator #}
{{ twigVariable ?? 'twigVariable not defined' }}

{# or check a field within an iterable #}
{{ twigVariable['fieldName'] ?? 'fieldName not defined' }}

The example above is the same as this longer is defined check:

{{ twigVariable is defined
    ? twigVariable
    : 'twigVariable not defined' }}

We can also add infinite fallbacks with more ?? conditions:

{{ twigVariable ?? fallbackVariable ?? 'Variables not defined' }}

Now compare the length of that short syntax with the equivalent using is defined in ternary:

{{ twigVariable is defined
    ? twigVariable
    : (fallbackVariable is defined
        ? fallbackVariable
        : 'twigVariable & fallbackVariable not defined'
    )
}}

Just for fun - your fallback can have a |default filter too. We can’t chain fallbacks after the default filter because it acts like a ‘catch all’:

{{ twigVariable ?? fallbackVariable|default('No variables defined') }}

If statement with null coalescing operator

We can also use a ?? within an ‘if statement’ to specify an instruction if twigVariable is undefined.

In this example, if twigVariable is undefined the test moves onto the next fallback. In this case it enters into the {% else %}:

{% if twigVariable ?? false %}
    The value is set and not empty
{% else %}
    Value is either undefined, false, 0, null, [] or {}
{% endif %}

An improved null coalesce operator replacement

nystudio107 has released a Twig extension for Craft 3 that patches the somewhat limited checks of the null coalescing operator.

The ??? Empty Coalescing operator is similar to the ?? null coalescing operator, but also ignores empty strings "" and empty arrays [] as well.

Once you install and activate this plugin you’ll be able to use the ??? to solidly check for a suitable fallback like this:

{{ twigVariable ??? fallbackVariable
    ??? 'Both variables either undefined, null, "" or {}' }}

Take a look at Empty Coalesce plugin on Github.

A side note about strict variables in Craft CMS

In Craft CMS 3, there’s a setting in config/general.php called devMode. By default, when devMode is set to true, YII_DEBUG gets set as true and in-turn strict_variables gets set as true.

  • If strict_variables=false (default)
    Twig won’t notify you about any undefined variables.
  • If strict_variables=true
    Twig throws a runtime error for all undefined variables - Variable "[name]" does not exist.

Some prefer to turn this setting off during development but that’s not best practice. You should know about undefined errors as soon as possible. You wouldn’t want to stumble across a broken variable later on would you?

Further reading