太陽がまぶしかったから

C'etait a cause du soleil.

PHP 初心者による Laravel 入門 その3 レイアウトの継承とコンポーネント

レイアウトの継承と可変部分の定義

 上記から引き続いて、『PHPフレームワークLaravel入門』を参考に Laravel に入門してみる。前回までは POST メソッドの受け取りとテンプレートエンジン blade での制御処理を実装した。

 前回までのテンプレート処理では HTML 全体の定義を書いてきたが、実際のアプリケーションを作成する場合にはヘッダ・フッタ・メニューなどの使い回し要素が発生する。 blade ではベースとなるレイアウトに @yeild@section で可変部分を定義して、個別レイアウト側で可変部分を補完するようなことができる。

views/layouts/base.blade.php

<!doctype html>
<html lang="{{ app()->getLocale() }}">
    <head>
        <meta charset="utf-8">
        <style>
        .flex-center {
                align-items: center;
                display: flex;
                justify-content: center;
            }
        </style>
        <title>@yield('title')</title>
    </head>

    <body>
    
    @section('menu')
    <ul>
        <li><a href="/hello">Hello</a></li>
        <li>@show</li>
    </ul>
    
    @yield('contents')

    copyright 2018 bulldra.
    
    </body>
</html>

views/hello/top.blade.php

 @extends('layouts.app') で上記ベースレイアウトを取得。

@extends('layouts.base')

@section('title','hello')

@section('menu')
    @parent
    追加メニュー
@endsection

@section('contents')
    <form method="POST" action="/hello">
        {{ csrf_field() }}
        <input type="text" name="target" value="" />
        <input type="submit" name="入力" />
    </form>
        
    @forelse ($data as $d)  
    <p>{{ $d }}</p>
    @empty
    <p>なーんもない</p>
    @endforelse
@endsection

 ベースレイアウト側で @yeild を定義すると、個別レイアウト側で定義した同名の @section で置き換えられる。ベースレイアウト側で定義した @section は個別レイアウト側の同名 @section で 呼び出して @parent でベースレイアウト側の定義を呼び出しながら @show 部分を書き換えられる。 @parent を使わない場合は単純な上書きとなるので、 @yeild の動作と変わらない。

コンポーネントとサブビューの組み込み

 ベースレイアウトを作成する方法は便利だが、警告メッセージなどの特定状態で表示される部品を定義するには適さない。このような場合には部品として定義したテンプレートをコンポーネントまたはサブビューとして利用する。

views/components/error.blade.php

<style>
.message { border:double 3px; }
</style>
<div class="message">ERROR! {{ $err_message }} </div>

views/hello/top.blade.php

@extends('layouts.base')

@section('title','hello')

@section('menu')
    @parent
    追加メニュー
@endsection

@section('contents')
    <form method="POST" action="/hello">
        {{ csrf_field() }}
        <input type="text" name="target" value="" />
        <input type="submit" name="入力" />
    </form>
        
    @forelse ($data as $d)  
    <p>{{ $d }}</p>
    @empty
    <p>なーんもない</p>
    @endforelse

    @component('components.error')
        @slot('err_message')
            ダメダメ1
        @endslot
    @endcomponent

    @component('components.error', ['err_message'=>'ダメダメ2'])
    @endcomponent

    @php
    $err_message = 'ダメダメ3'
    @endphp
    @include('components.error')

@endsection

 @component でテンプレート部品を指定して、 @slot 内で引数を定義する。 @include を利用した場合には呼び出し元の変数がそのまま利用できるので、マクロ展開されているイメージ。継承とコンポーネントの関係はオブジェクト指向における継承と委譲の関係と理解。

Note: @eachを使ってレンダされるビューは、親のビューから変数を継承しません。子ビューで親ビューの変数が必要な場合は、代わりに@foreachと@includeを使用してください。

Bladeテンプレート 5.6 Laravel

  @each によるコンポーネントの繰り返し構文もあるが、殆んどのシーンでは @foreach を使うべきだと思われるので割愛。