2

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 3

3

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.

2

How about doing something like this?

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

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.