【Laravel】Bladeテンプレートでレイアウトを共通化する
LaravelのBladeテンプレートにて用意されている「継承」と「セクション」という機能で、テンプレートを組み合わせてレイアウトを作成していく方法を軽くまとめておきたいと思います。
継承とセクション
「継承」とは、親ビューの持っている機能を子ビューが使うというイメージです。
ヘッダーやフッターなどの決まった共通部分は基底のテンプレート(親ビュー)に定義して、body の中だけを(子ビュー)で定義するといった使い方をします。
@sectionと@yield
@section
様々な部品を作成(定義)するために使用します。
以下のように記述します。
1 2 3 |
@section( 名前 ) …表示内容… @endsection |
これで指定した名前でセクションが用意されます。
このセクションは同じ名前の @yield にはめ込まれ表示されます。
また @section は継承したページで @section によって上書きすることも可能との事です(まだ良くわかっていない)。
@yield
@yield はセクションの内容をはめ込んで表示するためのものです。
以下のように使用します。
1 |
@yield( 名前 ) |
@yield で指定した名前のセクションがあると、そのセクションが @yield のところにはめ込まれます。
@yield は配置場所を示すものなので、 @yieldend のようなものは有りません。
レイアウトの作成
最終目的のHTML
親ビューは共通部分を記述し、子ビューにて詳細を記述するのが基本とのこと。
ということで、まずは最終的に記述したいHTMLを作ってからBladeの機能に置き換えてみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
<DOCTYPE HTML> <html lang="ja"> <head> <meta charset="UTF-8"> <title>ページタイトル|nodoame.net</title> <meta name="description" itemprop="description" content="ページごとの説明文を設定します"> <meta name="keywords" itemprop="keywords" content="キーワード1,キーワード2,キーワード3"> <link href="/css/star/layout.css" rel="stylesheet"> <link href="/css/star/index.css" rel="stylesheet"> </head> <body> <header class="header"> ヘッダー </header> <div class="contents"> <!-- コンテンツ --> <div class="main"> <p>コンテンツ内容(各ページにより異なる)</p> </div> <!-- 共通メニュー --> <div class="sub"> <ul> <li><a href="/star">INDEX</a></li>> <li><a href="/star/sun">SUN</a></li> <li><a href="/star/moon">MOON</a></li> </ul> </div> </div> <footer class="footer"> フッター </footer> </body> </html> |
ページごとに設定したい内容は以下とします。
- titleタグの内容
- description
- keywords
- page.css(ページ毎のCSS)
- コンテンツ内容
ベーステンプレート
以下がベースとなるテンプレートファイルです。
プロジェクトディレクトリ/resources/views へ「layout」ディレクトリを作成し、common.blade.php の名称で新規作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
<DOCTYPE HTML> <html lang="ja"> <head> <meta charset="UTF-8"> <title>@yield('title')|nodoame.net</title> <meta name="description" itemprop="description" content="@yield('description')"> <meta name="keywords" itemprop="keywords" content="@yield('keywords')"> <link href="/css/star/layout.css" rel="stylesheet"> @yield('pageCss') </head> <body> @yield('header') <div class="contents"> <!-- コンテンツ --> <div class="main"> @yield('content') </div> <!-- 共通メニュー --> <div class="sub"> @yield('submenu') </div> </div> @yield('footer') </body> </html> |
先にも書きましたが @yield() にて別途作成する内容を配置する仕組みとなっています。
この仕組み(機能)を使って、title、description、keywords、pageCss、header、content、submenu、footerを管理していきます。
スタイルシートは、プロジェクトディレクトリ/public へ「css」ディレクトリを作成してそちらへ配置することとします。
部品レイアウト
ヘッダー、フッター、サブメニュー用の部品レイアウトを作成します。
ヘッダー用(views/layout/header.blade.php)
1 2 3 4 5 |
@section('header') <header class="header"> ヘッダー </header> @endsection |
サブメニュー用(views/layout/submenu.blade.php)
1 2 3 4 5 6 7 |
@section('submenu') <ul> <li><a href="/star">INDEX</a></li> <li><a href="/star/sun">SUN</a></li> <li><a href="/star/moon">MOON</a></li> </ul> @endsection |
フッター用(views/layout/footer.blade.php)
1 2 3 4 5 |
@section('footer') <footer class="footer"> フッター </footer> @endsection |
継承レイアウト
先に作成したベースレイアウトを継承して実際のWEBページに使用するテンプレートを用意します。
ページごとに用意するものと捉えればわかりやすいでしょうか。
views/star/index.blade.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
@extends('layout.common') @section('title', 'インデックスページ') @section('keywords', 'キーワード1,キーワード2,キーワード3') @section('description', 'インデックスページの説明文です') @section('pageCss') <link href="/css/star/index.css" rel="stylesheet"> @endsection @include('layout.header') @section('content') <p>このページはインデックスページです。</p> <p><img src="/img/star/star.png" width="100" alt="星画像"></p> @endsection @include('layout.submenu') @include('layout.footer') |
HTMLらしい記述があまりなく、なんだか戸惑ってしまいます。
@extends()
レイアウトの継承設定として用います。
今回は layoutディレクトリ以下の common.blade.php を使用するという設定です。
@section
@endsection を使用する/しない、2種類の書き方があります。
使用しない場合は、名称に当てはめるテキストを設定します。
上記のサンプルでは内容では、ページごとのCSSを読み込むところで @endsection を使用しています。(6~8行目)
@include
サブビューと呼ばれる機能で、別のビューとして用意したものを読み込ませる機能です。(10行目)
インデックスページの結果
views/star/sun.blade.php
続けて「SUN」「MOON」ページも作成してみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
@extends('layout.common') @section('title', '太陽のページ') @section('keywords', 'キーワード4,キーワード5,キーワード6') @section('description', '太陽ページの説明文です') @section('pageCss') <link href="/css/star/sun.css" rel="stylesheet"> @endsection @include('layout.header') @section('content') <p>このページは太陽ページです。</p> <p><img src="/img/star/sun.png" width="100" alt="太陽画像"></p> @endsection @include('layout.submenu') @include('layout.footer') |
太陽ページの結果
views/star/moon.blade.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
@extends('layout.common') @section('title', '月のページ') @section('keywords', 'キーワード7,キーワード8,キーワード9') @section('description', '月ページの説明文です') @section('pageCss') <link href="/css/star/moon.css" rel="stylesheet"> @endsection @include('layout.header') @section('content') <p>このページは月ページです。</p> <p><img src="/img/star/moon.png" width="100" alt="月画像"></p> @endsection @include('layout.submenu') @include('layout.footer') |
月ページの結果
アクションとルーティング
コントローラー(アクション)と、ルーティングはそれぞれ以下の通りとします。
これで正解なのかが今のところまだ解りきっていないので、間違っている場合は訂正したいと思います。
アクション(app/Http/Controllers/StarController.php)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public function index() { return view('star.index'); } public function sun() { return view('star.sun'); } public function moon() { return view('star.moon'); } |
ルーティング(routes/web.php)
1 2 3 |
Route::get('/star', 'StarController@index'); Route::get('/star/sun', 'StarController@sun'); Route::get('/star/moon', 'StarController@moon'); |