ブレードで変数の値を表示するのによく使う括弧。{{ }} と {!! !!}2種類あります。これらに関しての話です。
{{ }} と {!! !!}の違い
{{ }} と {!! !!}の違いは、いたって簡単です。前者はhtmlをエスケープして、後者はエスケープしません。と言っても??なので、具体的に以下のようなブレードを作成して、違いを見てみましょう。
{{ $x }} {!! $x !!}
tinkerでこの$xに値を入れてブレードをビューすると、以下のようなHTML文が出力されます。
>>> view('test')->with(['x' => '<h1>hello</h1>'])->render(); => """ <h1>hello</h1>\n <h1>hello</h1>\n """
前者の表示は、HTMLのタグが見事にエスケープされていますが、後者はHTMLのタグがそのまま残っています。ブラウザでこれらを閲覧すると、
と表示の違いがはっきりします。
PHPにコンパイルされたブレード
先の例で使用したtest.blade.phpは、サーバーから表示される前にphpにコンパイルされてstorage/framework/viewsにキャッシュされます。コンパイルされたブレードの中身を見ると、
<?php echo e($x); ?> <?php echo $x; ?> <?php /**PATH /var/www/repos/l8x/resources/views/test.blade.php ENDPATH**/ ?>
お馴染みのphpファイルです(ブレードはphpファイル拡張子ですがphpファイルではありません)。なるほど単に標準のPHP関数のecho()
を使用しています。しかし、前者において、e()
という関数は標準のPHP関数ではありません。調べてみると、これはLaravelのヘルパーです。以下にその定義を掲載します。
... /** * Encode HTML special characters in a string. * * @param \Illuminate\Contracts\Support\DeferringDisplayableValue|\Illuminate\Contracts\Support\Htmlable|string|null $value * @param bool $doubleEncode * @return string */ function e($value, $doubleEncode = true) { if ($value instanceof DeferringDisplayableValue) { $value = $value->resolveDisplayableValue(); } if ($value instanceof Htmlable) { return $value->toHtml(); } return htmlspecialchars($value ?? '', ENT_QUOTES, 'UTF-8', $doubleEncode); } ...
標準関数のhtmlspecialchars()
が最終的にはHTMLタグをエスケープしていることわかります。
HtmlString
さて、ブレードで使用されている括弧の意味が解ったところで、先のtest.blade.phpを以下のように編集します。csrf_field()
は、LaravelのCSRFトークンのためのヘルパー関数です。
{{ csrf_field() }}
これをtinkerで先と同様にレンダリングします。今回は変数の渡しなしです。
>>> view('test')->render() => "<input type="hidden" name="_token" value="">\n"
おかしいですね。二重波括弧なのに、HTMLタグがエスケープされていません。どうしてでしょう?
csrf_field()
の定義を見てみましょう。
... /** * Generate a CSRF token form field. * * @return \Illuminate\Support\HtmlString */ function csrf_field() { return new HtmlString('<input type="hidden" name="_token" value="'.csrf_token().'">'); } ...
この関数が返しているのは、文字列ではなくHtmlStringのオブジェクトです。このオブジェクトがブレードでの括弧の変数の値とすると、エスケープ処理がされないのです。tinkerで試してみましょう。
>>> use Illuminate\Support\HtmlString; >>> $x = new HtmlString('<h1>hello</h1>'); => Illuminate\Support\HtmlString {#3517 html: "<h1>hello</h1>", } >>> e($x) => "<h1>hello</h1>"
HtmlStringを使う意味
表示される値にHTMLタグが含まれるかどうか前もってわかっていれば、{{ }} と {!! !!}の使いわけできますが、たいていはブレードを作成するのは開発者ではなくデザイナーさんです。HTML文を含むときに文字列ではなく、HtmlStringのオブジェクトとすれば、迷わずにいつも{{ }}の使用となります。
メルマガ購読の申し込みはこちらから。