ブレードで変数の値を表示するのによく使う括弧。{{ }} と {!! !!}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のオブジェクトとすれば、迷わずにいつも{{ }}の使用となります。
メルマガ購読の申し込みはこちらから。