TransWikia.com

How do Twig filters interact with concatenated strings and shorthand "if-else" ( `var ? true : false` ) strings?

Craft CMS Asked by Sandwich on September 4, 2021

If I am outputting content like this:

{{ entry.maxWidth|length ? entry.maxWidth ~ 'px' : 'unset' }}

…and I want to apply the |raw filter to the output (nevermind if it makes sense in this case; it’s just an example), where do I put it?

Do I go overboard, applying the desired filter to each bit of string, like this?

{{ entry.maxWidth|length ? 'max-width: '|raw ~ entry.maxWidth ~ 'px;'|raw : 'max-width: unset;'|raw }}

Is it applied after any string concatenation (~) is done?

{{ entry.maxWidth|length ? 'max-width: ' ~ entry.maxWidth ~ 'px;'|raw : 'max-width: unset;'|raw }}

Or is once per set of double-brackets ({{ ... }}) sufficient?

{{ entry.maxWidth|length ? 'max-width: '~ entry.maxWidth ~ 'px;' : 'max-width: unset;'|raw }}

3 Answers

You are asking about Twig's operator precedence:

The operator precedence is as follows, with the lowest-precedence operators listed first: ?: (ternary operator), b-and, b-xor, b-or, or, and, ==, !=, <=>, <, >, >=, <=, in, matches, starts with, ends with, .., +, -, ~, *, /, //, %, is (tests), **, ??, | (filters), [], and .:

| is higher precedence than ~, so 'this' ~ 'that' | raw will evaluate as 'this' ~ ('that' | raw). If you want ('this' ~ 'that') | raw then () is the way to go.

Personally, I would use () to disambiguate in both cases.

Correct answer by Marion Newlevant on September 4, 2021

Marion's answer beat me to this while I was writing but it's essentially very similar.

Replace raw with, say, upper and you'll be able to visually see what's going on:

// {{ entry.maxWidth|length ? 'max-width: '|raw ~ entry.maxWidth ~ 'px;'|raw : 'max-width: unset;'|raw }}
MAX-WIDTH: 160PX;

// {{ entry.maxWidth|length ? 'max-width: ' ~ entry.maxWidth ~ 'px;'|raw : 'max-width: unset;'|raw }}
max-width: 160PX;

// {{ entry.maxWidth|length ? 'max-width: '~ entry.maxWidth ~ 'px;' : 'max-width: unset;'|raw }}
max-width: 160px;

According to the Twig documentation:

The operator precedence is as follows, with the lowest-precedence operators listed first: ?: (ternary operator), b-and, b-xor, b-or, or, and, ==, !=, <=>, <, >, >=, <=, in, matches, starts with, ends with, .., +, -, ~, *, /, //, %, is (tests), **, ??, | (filters), [], and .:

Precedence = which gets evaluated first.

So in your example, the filters will happen first followed then by the concatenation (~). The ternary operator (? :) has very low precedence, which means it will get evaluated last.

Just like in algebra, if you put parenthesis around things, that will change the precedence which is also an easy way to group the whole thing into something you can filter as a whole.

So, if your goal is filter the entire output, put the entire expression in parenthesis, followed by the filter, so there's no ambiguity as to what's going on:

{{ ( entry.maxWidth|length ? 'max-width: '~ entry.maxWidth ~ 'px;' : 'max-width: unset;') | raw }}

Otto's answer is also a good way to clean up your expression.

Answered by RitterKnight on September 4, 2021

How about doing something like this?

{% set style = entry.maxWidth|length ? entry.maxWidth ~ 'px' : 'unset' %}
{{ style|raw }}

Answered by Oto Hlincik on September 4, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP