Twig で
- 比較判定の落とし穴
- 文字列結合
- 文字列結合したもののエスケープ回避
といった、いくつかのニッチなものや調べてもなかなか情報が出てこなかったについてメモしておきます。
経緯
いずれも type="number"
の input
タグで最小値・最大値をセットしようとしたときの話です。
$item = [ id => 'old', name => '年齢', condition => [ min => 0, max => 137 ], placeholder => 17 ];
という定義が予めPHP側であるという仮定で話を進めます。
比較判定の落とし穴
Twig の比較は PHP よりも緩いようです。例えば、
<input
type="number"
class="form-control"
id="{{ item.id }}"
name="{{ item.id }}"
placeholder="{{ item.placeholder }}"
{{ item.condition.min != null ? (' min="' ~ item.condition.min ~ '"')|raw : '' }}
{{ item.condition.max != null ? (' max="' ~ item.condition.max ~ '"')|raw : '' }}
>
という記述をすると、
<input
type="number"
class="form-control"
id="old"
name="old"
placeholder="17"
max="137"
>
と出力され、 min
が出力されませんでした。 null == 0
と判定されてしまったようです。
対処
<input
type="number"
class="form-control"
id="{{ item.id }}"
name="{{ item.id }}"
placeholder="{{ item.placeholder }}"
{{ item.condition.min is same as(null) ? '' : (' min="' ~ item.condition.min ~ '"')|raw }}
{{ item.condition.max is same as(null) ? '' : (' max="' ~ item.condition.max ~ '"')|raw }}
>
厳密な比較は same as
というのがあるとのことなので、それを利用します。否定の付け方がよく分からなかったので true
と false
の出力を反転させました。
文字列結合
上述で既に出てしまっていますが、 Twig の中での文字列結合は ~
とのこと。 PHP の癖で .
にしないように注意。
文字列結合したもののエスケープ回避
これも最初の例で出てしまっていますが、最初は以下のようにしていました。
<input
type="number"
class="form-control"
id="{{ item.id }}"
name="{{ item.id }}"
placeholder="{{ item.placeholder }}"
{{ item.condition.min is same as(null) ? '' : ' min="' ~ item.condition.min ~ '"'|raw }}
{{ item.condition.max is same as(null) ? '' : ' max="' ~ item.condition.max ~ '"'|raw }}
>
すると、以下のような出力に。
<input type="number" class="form-control" id="old" name="old" placeholder="17" min="e;"e;0"e;"e; max="e;"e;137"e;"e; >
|raw
を付けたのにエスケープされてしまっています。
対処
検索したところ、いくつか空振りの後にようやく文字列結合したものを |raw
出力する際は全体を括弧 ()
で括るという記述を発見。
<input type="number" class="form-control" id="{{ item.id }}" name="{{ item.id }}" placeholder="{{ item.placeholder }}" {{ item.condition.min is same as(null) ? '' : (' min="' ~ item.condition.min ~ '"')|raw }} {{ item.condition.max is same as(null) ? '' : (' max="' ~ item.condition.max ~ '"')|raw }} >
再掲になりますが、 (' min="' ~ item.condition.min ~ '"')|raw
という書き方ですね。これでようやく意図した出力になりました。