多くのページがあるサイトでは、全体の統一感を持たせるためにデザインを共通化させるのが一般的です。
今回は、レイアウトの継承や、テンプレートをセッションとして組み合わせてレイアウトを作成する方法を解説します。
参考書
全体のイメージ
全体のレイアウトを定義するファイルと、ページ内のコンテンツを配置するファイルを分けます。
レイアウト用のテンプレートを読み込み、そこに各要素をはめ込んで表示するというイメージです。
@section と @yield
@section
ページに表示される様々なコンテンツの区画を定義します。
@section( 名前 )
表示内容
@endsection
@yield
「@yield( 名前 )」で指定した名前と一致するセクションの内容をはめ込んで表示します。
yield(産出する、生み出す)の意味を知っていれば覚えやすいですね(^_^)
@yield( 名前 )
では実際に作ってみます。
「views」の中に「layouts」フォルダを作り、その中に「sampleLayout.blade.php」というファイルを作ります。

その中に、以下のように記述します。
ホント最小限のCSSしか書いてません…笑
<html>
<head>
<style>
body{
padding: 2rem;
}
h1{
color: blue;
}
</style>
</head>
<body>
<h1>@yield('title')</h1>
<div>
@yield('content')
</div>
<hr>
<footer>
@yield('footer')
</footer>
</body>
</html>
これが親テンプレートになります。
では続いて、「views/sample」の中の「index.blade.php」を編集します。
@extends('layouts.sampleLayout')
@section('title','タイトル')
@section('content')
<p>ここはcontentセクションです</p>
@endsection
@section('footer')
copyright 2020 hogehoge
@endsection
まず一行目ですが、
@extends('layouts.sampleLayout')
これで、「sampleLayout.blade.php」に書かれているレイアウトを親レイアウトとして継承しています。
そして二行目ですが、
@section('title','タイトル')
こちらは endsection で閉じられていません。
その代わり第2引数が指定されていますね。
セクションの中身がテキストや数字だけであれば、第2引数にその内容を入れて一行で済ませることもできます。
つまり、@yield(‘title’) は「タイトル」に置き換わるわけですね。
そして、残りの @section(‘content’) と @section(‘footer’) の中身が、それぞれ @yield(‘content’) と @yield(‘footer’) に当てはめられて表示されます。

コンポーネント
ときにはタイトルやフッターの表示などを独立した部品として一つのファイルで管理しておきたい場合があります。
そのようなときに使うのがコンポーネントになります。
コンポーネントを独立したテンプレートとして用意し、それらを組み合わせてレイアウトを構築することができます。
//コンポーネントの組み込み
@component( 名前 )
表示内容
@endcomponent
では、実際にコンポーネントを作成します。
今回は、タイトルとフッターをコンポーネントにして組み込みます。
「views」フォルダの中に「components」というフォルダを作り、その中に
「title.blade.php」「footer.blade.php」というファイルを作ります。
そして、それぞれ以下のように記述します。
//title.blade.php
<style>
h1{
color: blue;
}
</style>
<h1>{{$title}}</h1>
//footer.blade.php
<style>
footer{
background-color: blue;
color: white;
padding: 2rem;
position: absolute;
left: 0;
width: 100%;
}
</style>
<footer>{{$copyright}}</footer>
ではこれらのコンポーネントをテンプレートに組み込むため、「index.blade.php」を以下のように編集します。
@extends('layouts.sampleLayout')
@section('title')
@component('components.title')
@slot('title')
タイトル
@endslot
@endcomponent
@endsection
@section('content')
<p>ここはcontentセクションです</p>
@endsection
@section('footer')
@component('components.footer')
@slot('copyright')
copyright 2020 hogehoge
@endslot
@endcomponent
@endsection
まず、コンポーネントのファイルの指定は以下のようになります。
そして、@component 内の
で囲まれたコンテンツが、コンポーネントの同じ名前の変数にはめ込まれて表示されます。
つまり、
@slot('title')
タイトル
@endslot
この「title」という名前の付いたスロットの中身である「タイトル」という文字列が、
//title.blade.php
<h1>{{$title}}</h1>
「$title」に渡されて表示されるという仕組みですね。
では最後に「sampleLayout.blade.php」を修正します。
<html>
<head>
<style>
body{
padding: 2rem;
}
.content{
margin: 50px 0;
}
</style>
</head>
<body>
@yield('title')
<hr>
<div class="content">
@yield('content')
</div>
@yield('footer')
</body>
</html>

サブビュー
サブビューは、コンポーネントを少し使いやすくしたようなものになります。
スロットは使えませんが、連想配列で変数を渡すことはできます。
@include('テンプレート名', [ 値の指定 ])
では、サブビューを使って先ほど作った「index.blade.php」を少し変更します。
@extends('layouts.sampleLayout')
@section('title')
@include('components.title',['title'=>'タイトル'])
@endsection
@section('content')
<p>ここはcontentセクションです</p>
@endsection
@section('footer')
@include('components.footer',['copyright'=>'copyright 2020 hogehoge'])
@endsection
ブラウザには、先ほどと同じ表示になります。
@each を使ったコレクションビュー
@each ディレクティブは、配列から順に値を取り出してテンプレートにはめ込んで表示するものになります。
@each('テンプレート名', 配列, '変数名')
第2引数で配列を指定し、第3引数で配列から取り出した値を代入する変数名を指定します。
では、「views/components」の中に「user.blade.php」というファイルを作り、以下のように記述します。
<li>{{$user['name']}} [{{$user['mail']}}]</li>
「index.blade.php」の @section(‘content’) 部分を以下のように修正します。
@section('content')
<p>ここはcontentセクションです</p>
<ul>
@each('components.user', $users, 'user')
</ul>
@endsection
最後にコントローラ「SampleController.php」の index アクションを以下のように修正します。
public function index() {
$users = [
['name'=>'山田', 'mail'=>'yamada@sample.com'],
['name'=>'田中', 'mail'=>'tanaka@sample.com'],
['name'=>'鈴木', 'mail'=>'suzuki@sample.com']
];
return view('sample.index', ['users'=>$users]);
}
流れとしては、コントローラから配列users を「index.blade.php」に渡し、@each で user コンポーネントに値をひとつずつ渡し、<li>として表示されるという形になります。

今回は以上になります。
ご覧いただきありがとうございました(^^)
参考書
続きはこちら↓
コメント