
[laravel8] bladeの2つのレイアウト方法
上の記事で説明したようにviewファイルは
resources/views/
のディレクトリに保存しますが、例えば2つのviewファイルがある時どうなるでしょうか?
・ブログ記事一覧のページ resources/views/posts.blade.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ブログ記事一覧のページ</title>
</head>
<body>
ブログの記事一覧
</body>
</html>
・ブログ記事詳細ページ resources/views/post.blade.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ブログ記事詳細ページ</title>
</head>
<body>
ブログの記事詳細
</body>
</html>
これらの2つのファイルにjavascriptのファイルを追加したいときはどうしますか?
2つのファイルを開いて
<script src="~~~.js"></script>
を追加していきますか?
一般的には共通化できるところは共通化して、この場合だとjavascriptのファイルを追加するのは1回で済むようにします。
どのように共通化できるところを共通化していくか、2つの方法を紹介するので見ていきましょう。
テンプレート継承
この方法はまずHTMLの大元になる部分(共通化できる部分)を
resources/views/layout.blade.php
に記述します。
resources/views/layout.blade.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@yield('title')</title>
</head>
<body>
@yield('content')
</body>
</html>
ここでは@yieldディレクティブを使っています。このファイルがテンプレート全体(大元の)のファイルになります。
このテンプレートを利用したい場合はこのテンプレートを継承し、(この場合だと)titleとcontentを埋め込んでいく形になります。
では上で出てきたposts.blade.phpとpost.blade.phpのファイルでこのlayout.blade.phpを継承していきたいと思います。
・ブログ記事一覧のページ resources/views/posts.blade.php
@extends('layout')
@section('title')
ブログ記事一覧のページ
@endsection
@section('content')
ブログの記事一覧
@endsection
@extends('layout')
これはresources/views/のディレクトリにあるlayout.blade.phpを継承するという意味です。もしresources/views/の下にdesignというディレクトリを作りその中にあるlayout.blade.phpというファイルを継承したい場合は
@extends('design.layout')
と記述することになります。
@section('title')
ブログ記事一覧のページ
@endsection
このsectionディレクティブは@sectionで始まり@endsectionで終わります。その間にあるコードが、継承しているテンプレート(layout.blade.php)の中にある@yield('title')の箇所に入ってきます。
同様に
@section('content')
ブログの記事一覧
@endsection
はlayout.blade.phpの@yield('content')の箇所に入ります。
これを踏まえてpost.blade.phpを考えてみると簡単に以下のようになることがわかるかと思います。
・ブログ記事詳細ページ resources/views/post.blade.php
@extends('layout')
@section('title')
ブログ記事詳細ページ
@endsection
@section('content')
ブログ記事詳細
@endsection
bladeコンポーネント
2つ目の方法はbladeコンポーネントを使う方法です。
bladeコンポーネントを使うにはまずresources/views/ディレクトリの下にcomponentsディレクトリを作成します。
resources/views/components/
そしてこのディレクトリの中に保存したファイルはbladeコンポーネントとして使用することができるようになります。
layoutのbladeコンポーネントを作るためにresources/views/components/にlayout.blade.phpを作成し以下のようにします。
resources/views/components/layout.blade.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ $title }}</title>
</head>
<body>
{{ $content }}
</body>
</html>
ではこのbladeコンポーネントをどのように使うのでしょうか?
このコンポーネントを使うにはまず
<x-(コンポーネントの名前)></x-(コンポーネントの名前)>
のようなHTMLタグのようなものを作ります。
そしてtitleとcontentを指定する方法が2つあるのですが、言葉で説明するよりは例を見た方がわかりやすいので先ほどのposts.blade.phpを例に見てみましょう。
・ブログ記事一覧のページ resources/views/posts.blade.php
方法1
<x-layout content="ブログ記事一覧" title="ブログ記事一覧のページ"></x-layout>
コンポーネントの名前がlayout.blade.phpなのでタグは
<x-layout></x-layout>
となります。
layoutコンポーネントでは変数の$titleと$contentがあったが、これらはタグのattributeとして指定しています。
content="ブログ記事一覧" title="ブログ記事一覧のページ"
方法2
2つ目の方法はslotを使用する方法です。
<x-layout>
<x-slot name="content">
ブログ記事一覧
</x-slot>
<x-slot name="title">
ブログ記事一覧のページ
</x-slot>
</x-layout>
この方法では<x-layout>のattributeは使用せず、
<x-slot></x-slot>
を配置し、そのnameでcontentとtitleを指定し、表示したい内容を指定しています。
またこの方法ではデフォルトslotを使うことができます。
まずlayout.blade.phpで$slotと置いておくと
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ $title }}</title>
</head>
<body>
{{ $slot }}
</body>
</html>
posts.blade.phpでx-slotタグを使用しない文字列は$slotになります。
<x-layout>
ブログ記事一覧
<x-slot name="title">
ブログ記事一覧のページ
</x-slot>
</x-layout>
ブログ記事一覧は<x-slot></x-slot>に囲まれていないのでデフォルト値として扱われ$slotに入ります。
これを応用するとbuttonコンポーネントなどを作るのも簡単ですね。
resources/views/components/button.blade.php
<button {{ $attributes }}>{{$slot}}</button>
最後に
今回紹介した2つの方法について、どっちが良いとか悪いとか全くありません。私の感覚では最近はみんなbladeコンポーネントを使い始めているのかな?って感じることはありますが、コンポーネントが良いとかそういうことではありません。他人のコードを読む時などがある場合は両方知っておくことはとても大切です。