7. コンポーネント
コンポーネントの基本
コンポーネントとは
Component(コンポーネント)は部品という意味で、Webアプリケーションでは、HTMLやプログラムを共通化したファイルのことを指します。コンポーネント化することで何度も同じコーディングをせず、効率的に開発ができます。
レイアウトとは
Layout(レイアウト)は、メニューやヘッダーなどの共通部分を1ファイルで構成するコンポーネントファイルです。例えばHTMLのheadタグやbodyタグなどのレイアウトファイルを用意することで、各ページはレイアウト部分をコーディングせずに済みます。
<html>
<head>
<title>Shopping</title>
</head>
<body>
ページごとのコンテンツを表示
</body>
</html>
Laravelのレイアウト
Laravelのレイアウトの作成方法はいくつかあります。
- ディレクティブ
- Blade Components
- Inertia
- LiveWire
従来のBladeレイアウト
@extends、@yield、@section の専用ディレクティブでレイアウトを利用する、従来のBladeレイアウトです。
Blade Componentsによるレイアウト
Blade Componentsは、再利用可能なUIコンポーネントを作成してレイアウトする方法で、Laravelバージョン7.x以降で利用できます。
Inertia
Inertiaは「React」と「Vue」に対応したフロントエンド開発ライブラリで、Laravelバージョン8.x以降で利用できます。
LiveWire
LiveWireは「React」や「Vue」のようなリアクティブなフロントエンド開発に対応したライブラリで、Laravelバージョン8.x以降で利用できます。サーバーサイド、JavaScriptをほとんどコーディングせず、PHP&Laravelだけで開発します。
Vite
Laravelのコンポーネントは、バージョンアップにより非常に多様になりBladeだけでなくJavaScriptフレームワークで作成することもできます。 これにより、JavaScript、CSSモジュールのビルドツールが必要になります。
Viteとは
「Vite」は、Vue.jsをはじめとするJavaScriptフレームワークやライブラリ開発にのビルドツールです。最新のLaravelのビルドツールは、WebpackをベースとしたLaravel MixからViteに変更になりました。
@vite()
@viteディレクティブはBladeテンプレート内でJavaScriptやCSSモジュールをロードできます。
@vite(['resources/css/app.css', 'resources/js/app.js'])
Blade Components
レイアウト
レイアウトファイル作成
「views/layouts/」に「app.blade.php」などのレイアウトファイルを作成します。
レイアウト名.blade.php
@slot
レイアウト内に @slotディレクティブを利用すると、ページコンテンツを挿入できます。
layouts/app.balde.php
<!DOCTYPE html>
<html lang="ja">
<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>
{{ $slot }}
</body>
</html>
ページコンポーネント
各コンポーネントでレイアウト利用する場合、x-レイアウト名-layout とします。
<x-レイアウト名-layout>
<!-- コンテンツを記述 -->
</x-レイアウト名-layout>
ページコンポーネントの作成
レイアウトを「layouts/app.balde.php」としたページコンポーネントの例です。
ページコンポーネント
<x-app-layout>
<div>コンテンツ</div>
</x-app-layout>
従来のBladeレイアウト
3つのディレクティブ
Laravel7.x以前までは、3つのディレクティブを利用して、レイアウトとページコンポーネントを作成していました。
- @yield
- @extends
- @section
レイアウトとページコンポーネントの構成
レイアウトは @yeild、ページコンポーネントは @extends、@sectionで構成します。
@yield
@yieldは、レイアウトにページコンポーネントを表示するディレクティブです。
app.blade.php
@yield(セクション名)
@extends
@extendsは、ページコンポーネントからレイアウトファイルを読み込むためのディレクティブです。
@extends(layouts.レイアウト名)
@section
@sectionは、レイアウトに表示するページコンポーネントのディレクティブです。
@section(セクション名, データ)
コンテンツ
@endsection
- 第1引数:セクション名、@sectionタグの中にコンテンツ
- 第2引数:データ
レイアウト
レイアウトファイル作成
Blade Componentsのレイアウト同様「views/layouts/」に「app.blade.php」などのレイアウトファイルを作成します。
レイアウト名.blade.php
layouts/app.blade.php
<html lang="ja">
<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>
ページコンポーネント作成
レイアウト「layouts/app.blade.php」を利用して、ページコンポーネントを表示する例です。
ページコンポーネント
@extends('layouts.app')
@section('title', 'Home')
@section('content')
<div>コンテンツ</div>
@endsection
レイアウト作成
ファイル構成
/
├── about.blade.php
├── item
│ └── show.blade.php
├── layouts
│ └── app.blade.php
├── components
│ └── head.blade.php
├── search.blade.php
└── welcome.blade.php
レイアウトファイルの作成
「app.blade.php」ファイルの作成
「layouts」フォルダに「app.blade.php」を作成します。 「resources/views/」フォルダに「app.blade.php」を作成します。
CSSフレームワーク
CSSフレームワーク「Bootstrap5」を利用するため、headタグにCDNリンクを記述します。
layouts/app.blade.php
<!DOCTYPE html>
<html lang="ja">
<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>Shop</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
</head>
<body>
</body>
</html>
最新はTailwind CSS
Laravelの旧バージョンのCSSフレームワークは「Bootstrap」を採用していましたが、最新バージョンでは「Tailwind CSS」が標準となりました。
Blade Componentsで作成
app.blade.php
...
<body>
<main class="container">
{{ $slot }}
</main>
</body>
...
従来のBladeで作成
セクションの読み込み
@yield() でセクションを指定してBladeファイルを読み込みます。セクション名は「content」とします。
app.blade.php
...
<body>
<main class="container">
@yield('content')
</main>
</body>
...
ページコンポーネントの修正
「about」ページ
セクション作成
「about.blade.php」で、セクション @section('content') を追加し、その中にコンテンツを入れます。
about.blade.php
@section('content')
<h2>About</h2>
<p>This is about page.</p>
@endsection
レイアウト読み込み
@extends でレイアウト「app.blade.php」を読み込みます。
about.blade.php
@extends('layouts.app')
@section('content')
<h2>About</h2>
<p>This is about page.</p>
@endsection
コンテンツが表示されたか確認してみましょう。
結果
その他コンポーネント
従来のディレクティブ
@include
@include でコンポーネントを読み込むディレクティブで、PHP標準の include と同じです。
@include(ファイルパス, データ)
@component
@component は @include を拡張したディレクティブです。
@component(ファイルパス)
@endcomponent
@slot
@component は通常、スロット(@slot)を併用して利用します。@slot は表示するコンポーネントの変数として機能します。
@component(ファイルパス)
@slot(スロット名)
コンテンツ
@endslot
@endcomponent
- 第2引数:データを受け渡す
コンポーネント作成
コンポーネントフォルダ作成
コンポーネント管理用に「views/components/」フォルダを作成します。
コンポーネントファイル作成
「head.blade.php」ファイルを作成します。
make:component で作成
make:component コマンドでコンポーネントファイルを作成できます。
ターミナル
php artisan make:component head
この場合「app/View/」にも、Headクラスのコンポーネントも作成されます。
コンテンツ追加
「components/head.blade.php」で、headタグ部分を記述します。
components/head.blade.php
<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>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
</head>
- titleタグに変数「title」を表示できるようにしておきます。
コンポーネントの読み込み(Blade Components)
「app.blade.php」レイアウトから、x-headタグで「head.blade.php」コンポーネントを読み込みます。
layouts/app.blade.php
<!DOCTYPE html>
<html lang="jp">
<x-head>
<x-slot name="title">Shop</x-slot>
</x-head>
<body>
<main class="container">
{{ $slot }}
</main>
</body>
</html>
- x-slotタグを使って変数「title」を受け渡し
コンポーネントの読み込み(従来)
「app.blade.php」レイアウトから、@include で「head.blade.php」コンポーネントを読み込みます。
layouts/app.blade.php
<!DOCTYPE html>
<html lang="jp">
@include('components.head', ['title' => 'Shop'])
<body>
<main class="container">
@yield('content')
</main>
</body>
</html>
- @include の第2引数で、変数をコンポーネントに受け渡します
演習
練習1
「search/」「item/{id}」「item/edit/{id}」のコンテンツをレイアウトで表示してみましょう。