Twigフィルターは、連結された文字列および省略形の "if-else"( `var?true:false`)文字列とどのように相互作用しますか?


2

このようなコンテンツを出力している場合:

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

...そして|rawフィルターを出力に適用したい(この場合、それが意味があるかどうかは気にしないでください。これは単なる例です)、どこに配置しますか?

次のように、文字列の各ビットに必要なフィルタを適用して過剰に行きますか?

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

文字列の連結(~)が行われたに適用されますか?

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

または、ダブルブラケット({{ ... }})のセットごとに1回で十分ですか?

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

How about doing something like this?

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

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

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.