Twig の Tips

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 というのがあるとのことなので、それを利用します。否定の付け方がよく分からなかったので truefalse の出力を反転させました。

文字列結合

上述で既に出てしまっていますが、 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 という書き方ですね。これでようやく意図した出力になりました。

参考

この記事を書いた人

アルム=バンド

フロントエンド・バックエンド・サーバエンジニア。LAMPやNodeからWP、Gulpを使ってejs,Scss,JSのコーディングまで一通り。たまにRasPiで遊んだり、趣味で開発したり。