リモート開発メインのソフトウェア開発企業のエンジニアブログです

Laravelのテンプレートbladeでの@include @yield @sectionの違い

はじめに

Laravelのテンプレートエンジンbladeを使ってレイアウトを作成するときに出てくる@yield, @section, @includeといったものの違いがイマイチ理解できなかったので、それぞれどのような場合に対して使うのが適切なのか調べてまとめてみました。

この記事では、よく使われるパターンである親テンプレート(レイアウトview)+子テンプレート(コンテンツview)を使う際の@yield, @section, @includeの違いについて詳しく見ていきます。

Laravelの公式ドキュメントでは@yield+@sectionと@includeで分けて取り扱っていて個人的にわかりやすかったので、ここでも@yield+@section👉@includeという流れで分けて説明しています。

https://laravel.com/docs/5.8/blade

Moba Pro

親テンプレートにおける@yieldと@sectionの違いについて

親テンプレート(レイアウト)ではまずは@yieldと@sectionの二種類の違いを抑えましょう。@includeに関しては一旦置いておいて、後で説明します。

親テンプレート(レイアウトview)

<!-- Stored in resources/views/layouts/app.blade.php -->

<html>
    <head>
        <title>アプリ名 - @yield('title')</title>
    </head>
    <body>
        @section('sidebar')
            <p>メインのサイドバー(共通部分)</p>
        @show

        <div class="container">
            @yield('content')
        </div>

        <footer class="footer">
            <p>フッター(共通部分)</p>
        </footer>
    </body>
</html>

親テンプレートでの@yield

共通化せずにコンテンツview毎にダイナミックに変化するものやページ毎に設定するようなものは@yieldを使います。(それぞれのページのタイトル、メインコンテンツなど・・)

yieldという言葉の意味が日本語で捉えづらいのでいつも混乱していたのですが、「生む」という意味で考えると、常にそれぞれのページで生み出すコンテンツに使うと覚えて個人的にはスッキリさせることができました。

@yieldは継承ができないので、常に子テンプレートでテンプレート毎の内容を記述していくことになります。

親テンプレートでの@section

一方、@sectionは継承ができます。親テンプレート(レイアウトview)に記述した内容を子テンプレート(コンテンツview)で使うことができるというのが@yieldとの大きな違いです。なので、親テンプレート(レイアウトview)における@sectionは、共通化してかつ個別の部分を追加していくようなものには@sectionを使います。(サイドバー、フッターなど・・※このサンプルではフッターは仮に全ページ共通のものとしています。)

親テンプレートでの@sectionは@showで閉じます。子テンプレートで個別の部分を追加するときは、@showの部分に個別の部分が追加されていくることになります。

子テンプレート(コンテンツview)

<!-- Stored in resources/views/home.blade.php -->

@extends('layouts.app')

@section('title', 'メインコンテンツのタイトル')

@section('sidebar')
    @parent

    <p>メインのサイドバー(共通部分)に追加される個別の部分</p>
@endsection

@section('content')
    <p>メインコンテンツ</p>
@endsection

子テンプレートでは、まず@extendsで親テンプレートを読み込みます。そして、@section〜@endsectionを使って親テンプレートにおいて@yieldや@section〜@showで示した部分に子テンプレートの内容を記述していきます。

親テンプレートで@section〜@showで示した部分に対しては、子テンプレートで@parentを使って親テンプレートの内容を継承しつつ、個別の内容を追加することができます。

@includeの使い方

それではここまでの内容を押さえた上で@includeを使い方を確認します。

@includeを使うことで、外部のテンプレートを取り込むことができ、レイアウトの記述をすっきりとさせることができます。以下のサンプルコードでは、サイドバーとフッターを別テンプレートとして分離し、親テンプレートでは@includeを使って読み込んでいます。

すでに扱ったサイドバーにおける@sectionで定義している部分も@includeを使って同様に外部のテンプレートファイルに分離することができます。ここではincというディレクトリを新たに作成してそこにsidebar-file.blade.phpとfooter-file.blade.phpというテンプレートを新たに作成したうえで、それぞれのファイルにサイドバーとフッターの内容を記述しています。

※@sectionで定義した’sidebar’と’footer’というセクション名と混合しないように、このサンプルでは説明のためにsidebar-fileとfooter-fileという名前に仮にそれぞれしています。

親テンプレート(レイアウトview)

<!-- Stored in resources/views/layouts/app.blade.php -->

<html>
    <head>
        <title>アプリ名 - @yield('title')</title>
    </head>
    <body>
        @include('inc.sidebar-file')

        <div class="container">
            @yield('content')
        </div>

        @include('inc.footer-file')
    </body>
</html>

親テンプレートでは@include(‘ファイル名’)とすることで外部テンプレートの内容を取り込んでいます。以下のような形で外部テンプレートに変数を渡すこともできます。

@include('ファイル名', ['some' => 'data'])

サイドバー

<!-- Stored in resources/views/layouts/inc/sidebar-file.blade.php -->

@section('sidebar')
    <p>メインのサイドバー(共通部分)</p>
@show

サイドバーの内容は@sectionで定義しておくことで、@includeしないときと同様に子テンプレートにおいて親テンプレートの内容を継承した上で個別に追加することができます。

フッター

<!-- Stored in resources/views/layouts/inc/footer-file.blade.php -->

<footer class="footer">
    <p>フッター(共通部分)</p>
</footer>

このサンプルではフッターは仮に共通のものとして、そのまま記述しています。

もし個別の内容を追加したい場合などはサイドバー同様に@sectionを使うことで子テンプレートでこのフッターの内容を継承した上で内容を追加することが可能です。

子テンプレート(コンテンツview)

<!-- Stored in resources/views/home.blade.php -->

@extends('layouts.app')

@section('title', 'メインコンテンツのタイトル')

@section('sidebar')
    @parent

    <p>メインのサイドバー(共通部分)に追加される個別の部分</p>
@endsection

@section('content')
    <p>メインコンテンツ</p>
@endsection

子テンプレートでは親テンプレートで@includeを使っていても、記述方法は変わりません。親テンプレートにincludeされた部分も親テンプレートに記述されているものと同様に扱うことができます。

まとめ

レイアウトで使われている@yieldと@sectionと@includeについてはじめは違いがはっきりせずに混乱していたのですが、公式ドキュメントの説明の通りに@yieldと@sectionと@includeを分けて考えたことで個人的にすっきりと整理することができましたので、皆さんの参考になれば幸いです。

https://laravel.com/docs/5.8/blade

← 前の投稿

Build Infrastructures with Terraform

次の投稿 →

AWS CLIで標準入出力でS3オブジェクトを操作する方法

コメントを残す