[Laravel] Blade での変数出力時の記法で三重波括弧「{{{}}}」があった件

2018年9月6日ITLaravel, PHP

Blade で変数を出力する際に書く「{{ }}」、「{!! !!}」が内部でどう処理されているのか調べていたら、なんと「{{{ }}}」がございまして、少し調べてみました。

Laravel 5 より前のバージョンでは、、
三重波括弧「{{{ }}}」が変数をエスケープして出力して、
二重波括弧「{{ }}」 が変数をエスケープせずに出力

だったらしく

Laravel 5 以降は、、
二重波括弧「{{}}」 が変数をエスケープして出力して、
波括弧とエクスクラメーション・マーク2つの「{!! !!}」が変数をエスケープせずに出力

なので、現行は、、

・三重波括弧「{{{ }}}」が変数をエスケープして出力
・二重波括弧「{{}}」 が変数をエスケープして出力
・波括弧とエクスクラメーション・マーク2つの「{!! !!}」が変数をエスケープせずに出力

となります。

三重波括弧「{{{ }}}」は後方互換のために残っているようですね。

実際に試してみますと、、

[検証環境]
PHP 7.2.4
MySQL 5.7.22
Laravel 5.5.40

@php
    $item = '<h1>Hello world!</h1>'
@endphp
{{ $item }}<br>
{{{ $item }}}<br>
{!! $item !!}

イメージ画像
laravel-triple-curly-braces.png

三重波括弧、二重波括弧はエスケープされてますね。

フレームワーク内の定義箇所を調べてみると、下記のようです。
・三重波括弧は “escaped echos”
・二重波括弧は “regular echos”
・波括弧とエクスクラメーション・マーク2つは “raw echos”

/Illuminate/View/Compilers/BladeCompiler.php

/**
 * Array of opening and closing tags for escaped echos.
 *
 * @var array
 */
protected $escapedTags = ['{{{', '}}}'];

/**
 * Array of opening and closing tags for regular echos.
 *
 * @var array
 */
protected $contentTags = ['{{', '}}'];

/**
 * Array of opening and closing tags for raw echos.
 *
 * @var array
 */
protected $rawTags = ['{!!', '!!}'];

/**
 * The "regular" / legacy echo string format.
 *
 * @var string
 */
protected $echoFormat = 'e(%s)';

実装箇所は、ちょっとややこしいですが、

三重波括弧 compileEscapedEchos 内の e()
二重波括弧 compileRegularEchos 内の echoFormat
波括弧とエクスクラメーション・マーク2つ はエスケープ処理に該当する箇所はなさげです。

/Illuminate/View/Compilers/Concerns/CompilesEchos.php

/**
 * Compile the escaped echo statements.
 *
 * @param  string  $value
 * @return string
 */
protected function compileEscapedEchos($value)
{
    $pattern = sprintf('/(@)?%s\s*(.+?)\s*%s(\r?\n)?/s', $this->escapedTags[0], $this->escapedTags[1]);

    $callback = function ($matches) {
        $whitespace = empty($matches[3]) ? '' : $matches[3].$matches[3];

        return $matches[1] ? $matches[0] : "<?php echo e({$this->compileEchoDefaults($matches[2])}); ?>{$whitespace}";
    };

    return preg_replace_callback($pattern, $callback, $value);
}

/**
 * Compile the "regular" echo statements.
 *
 * @param  string  $value
 * @return string
 */
protected function compileRegularEchos($value)
{
    $pattern = sprintf('/(@)?%s\s*(.+?)\s*%s(\r?\n)?/s', $this->contentTags[0], $this->contentTags[1]);

    $callback = function ($matches) {
        $whitespace = empty($matches[3]) ? '' : $matches[3].$matches[3];

        $wrapped = sprintf($this->echoFormat, $this->compileEchoDefaults($matches[2]));

        return $matches[1] ? substr($matches[0], 1) : "<?php echo {$wrapped}; ?>{$whitespace}";
    };

    return preg_replace_callback($pattern, $callback, $value);
}

/**
 * Compile the "raw" echo statements.
 *
 * @param  string  $value
 * @return string
 */
protected function compileRawEchos($value)
{
    $pattern = sprintf('/(@)?%s\s*(.+?)\s*%s(\r?\n)?/s', $this->rawTags[0], $this->rawTags[1]);

    $callback = function ($matches) {
        $whitespace = empty($matches[3]) ? '' : $matches[3].$matches[3];

        return $matches[1] ? substr($matches[0], 1) : "<?php echo {$this->compileEchoDefaults($matches[2])}; ?>{$whitespace}";
    };

    return preg_replace_callback($pattern, $callback, $value);
}

以上、今となってはどうでもいいっちゃどうでもいい、「Blade の三重波括弧について調べてみたお!」でした。

ひとこと

歴史を感じますね。でも、波括弧三段重ねはさすがに多過ぎちゃうんか、と思いました。

スポンサーリンク

Posted by nobuhiro harada