LarvelはBladeなるテンプレート言語を備えています。
Bladeテンプレート 5.7 Laravel
便利は便利なのですが独自な上、説明もざっくばらんなので詳細に中身を把握するのは難しいです。
artisan view:cacheはresources以下のBladeファイルのキャッシュを生成するコマンドです。このコマンドで生成されるPHPファイルはBladeをPHP言語にコンパイルした結果です。コンパイル後のファイルを読むことでBladeが何をやっているのか少しわかりやすくなります。
例えば次のコードをコンパイルすると
@section('header')
@endsection
@yield('header')
@section('footer')
@show
@section('body')
@overwrite
@yield('body')
次の様になります。
<?php $__env->startSection('header'); ?>// @section
<?php $__env->stopSection(); ?>// @endsection
<?php echo $__env->yieldContent('header'); ?>// @yield
<?php $__env->startSection('footer'); ?>// @section
<?php echo $__env->yieldSection(); ?>// @show
<?php $__env->startSection('body'); ?>// @section
<?php $__env->stopSection(true); ?>// @overwrite
<?php echo $__env->yieldContent('body'); ?>// @yield
こうやってPHPコードに直すとやっていることを追いかけられるようになり、中身を知ることが出来ます。
@endsection, @yield, @show, @overwriteはそれぞれ@sectionと密に関わるディレクティブです。
Bladeテンプレート 5.7 Laravel#レイアウト定義
@endsectionはsectionで定義を始めたコードの終点を示し、@yieldはsectionの出力を示し、@showはsectionで定義を始めたコードの終点であり即時展開を示し、overwriteは同名sectionの上書きを行うsection定義の終点を示します。これだけだとどういうこととなりますがコードを読むと少しわかります。@sectionの中身であるstartSectionの内容が次です。
/**
* Start injecting content into a section.
*
* @param string $section
* @param string|null $content
* @return void
*/
public function startSection($section, $content = null)
{
if ($content === null) {
if (ob_start()) {// ここが大事
$this->sectionStack[] = $section;
}
} else {
$this->extendSection($section, $content instanceof View ? $content : e($content));
}
}
obstart()でこれ以降の出力(ブラウザに映る予定のHTMLコードなど)をバッファにため込みます。これは改めて命令されるまで出力されません。ついで@endsection,@overwriteの中身であるstopSection()が次です。
/**
* Stop injecting content into a section.
*
* @param bool $overwrite
* @return string
*
* @throws \InvalidArgumentException
*/
public function stopSection($overwrite = false)
{
if (empty($this->sectionStack)) {
throw new InvalidArgumentException('Cannot end a section without first starting one.');
}
$last = array_pop($this->sectionStack);
if ($overwrite) {
$this->sections[$last] = ob_get_clean();
} else {
$this->extendSection($last, ob_get_clean());
}
return $last;
}
ob_get_clean()でバッファの内容を取得し、出力バッファを削除します。@overwriteはこの$overwrite=trueでstopSectionを呼び出しています。これにより問答無用でプロパティsectionsの末尾にバッファを書き込んでいます。@overwriteに引数がないのは必ず末尾を参照していたせいです。
$overwrite=falseの時はextendSection()へ回って、もし以前に定義していればそちらを呼び出すようにしています。
@showの中身であるyieldSection()、@yieldの中身であるyieldContent()が次です。
/**
* Stop injecting content into a section and return its contents.
*
* @return string
*/
public function yieldSection()
{
if (empty($this->sectionStack)) {
return '';
}
return $this->yieldContent($this->stopSection());
}
/**
* Get the string contents of a section.
*
* @param string $section
* @param string $default
* @return string
*/
public function yieldContent($section, $default = '')
{
$sectionContent = $default instanceof View ? $default : e($default);
if (isset($this->sections[$section])) {
$sectionContent = $this->sections[$section];
}
$sectionContent = str_replace('@@parent', '--parent--holder--', $sectionContent);
return str_replace(
'--parent--holder--', '@parent', str_replace(static::parentPlaceholder($section), '', $sectionContent)
);
}
yieldSectionは短縮形の様なものです。stopSection、yieldContentの順に呼び出し、最後に宣言したsectionを閉じ、出力しています。
yieldContentはプロパティ$this->sectionsの中から目当てのsectionを選び、整形して返しているのみです。
@endsection, @yield, @show, @overwriteはBlade内部では糖衣構文として役割に応じた大きく違う名前を与えられていましたが、実際にはちょっとした違う引数で呼び出される同じ関数らであることがわかります。