Laravel初学者による学習のまとめ #2
#1はこちら
コンポーネント
<x-guest-layout> のように書くことでコンポーネントが使える。
- resources/views/components/配下
クラスを使わない時
匿名コンポーネントと呼ばれる
<div>
<div>
{{ $trigger }}
</div>
</div>
- app/View/Components/配下
クラスを使う時
クラスコンポーネントと呼ばれる
<!-- このx-app-layoutを追ってみる -->
<x-app-layout>
<x-slot name="header">
<h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">
{{ __('Dashboard') }}
</h2>
</x-slot>
<div class="py-12">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div class="bg-white dark:bg-gray-800 overflow-hidden shadow-sm sm:rounded-lg">
<div class="p-6 text-gray-900 dark:text-gray-100">
{{ __("You're logged in!") }}
</div>
</div>
</div>
</div>
</x-app-layout>
<?php
namespace App\View\Components;
use Illuminate\View\Component;
use Illuminate\View\View;
class AppLayout extends Component
{
/**
* Get the view / contents that represents the component.
*/
public function render(): View
{
return view('layouts.app');
// ここが重要で、resources/views/layouts/app.blade.phpを使っている
}
}
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>{{ config('app.name', 'Laravel') }}</title>
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.bunny.net">
<link href="https://fonts.bunny.net/css?family=figtree:400,500,600&display=swap" rel="stylesheet" />
<!-- Scripts -->
@vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
<body class="font-sans antialiased">
<div class="min-h-screen bg-gray-100 dark:bg-gray-900">
@include('layouts.navigation')
<!-- Page Heading -->
@if (isset($header))
<header class="bg-white dark:bg-gray-800 shadow">
<div class="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
{{ $header }}
</div>
</header>
@endif
<!-- Page Content -->
<main>
{{ $slot }}
</main>
</div>
</body>
</html>
使い分け
■ 匿名コンポーネント
メリット
- 1ファイル=コンポーネントで探しやすい
- ボタンやドロップダウンなど、マークアップ中心のUIに向いている
- 見た目とprops(設定値。部品の見た目や動きを変えるための引数)だけで足りるときに最適
向かないこと
- DBやサービスからデータをとる
- コンストラクタ(1回だけ呼ばれる特別なメソッド。組み立て直後の初期設定)で依存を注入する場合
- 複雑な条件分岐や計算をPHPでまとめたいとき
→ プロジェクト全体で「部品」として量産する UI パーツが向いている
■ クラスコンポーネント
メリット
- PHP のロジックを書ける(メソッド、型、DI、テスト)
- どのビューを使うかをクラスで決められる(layouts.app のように、レイアウト名とコンポーネント名を分けられる)
- コンストラクタで User やサービスを受け取れる
- 同じコンポーネント名で、状況に応じて別ビューを返す、など柔軟
デメリット
- ファイルが2つ以上になり、少し重い
- 単純なボタン1個には過剰
→ レイアウトやデータの取得、権限チェック、計算が必要なもの、コンポーネント単体をPHPUnitでテストしたいときに向いている
クラスコンポーネントはPHPクラス+Bladeビューの2段構成
class AppLayout extends Component
{
public function __construct(
public User $user, // Laravel が自動で「今のログインユーザー」を入れてくれる
) {}
public function render(): View
{
return view('layouts.app');
// views/layouts/app.blede.phpを使う
}
}
こんにちは、{{ $user->name }} さん
このようにデータをフロントに渡すことができる
slot
{{ $slot }} は、親ページがコンポーネントに渡した「本文の HTML」が入る場所。
枠(レイアウト)の真ん中に、ページごとの中身を差し込むための「穴」のようなもの。
子. 枠を作る
<div>
<p>お知らせ</p>
<div>
{{ $slot }} // ここに親の文章が入る
</div>
<p>以上</p>
</div>
<x-app-layout> と </x-app-layout> の あいだ に書いた HTML が、子コンポーネントへ渡されます
親. 中身を渡す
<x-card>
明日は雨です。傘を持ってください。 // {{ $slot }}に入れたいものを書く
</x-card>
ブラウザには以下のように表示される
お知らせ
明日は雨です。傘を持ってください。 // これが $slot の中身
以上
このようにコンポーネントを呼び出すときに<x-></x->の間に書いたものを、コンポーネントの一部として当てはめることができる
名前付きslot
{ $hoge }などのように任意のスロット名をつけられる。
<div>
<p>お知らせ</p>
<div>
{{ $slot }}
</div>
<div>
{{ $yohou }}
</div>
<p>以上</p>
</div>
<x-card>
明日は雨です。傘を持ってください。
<p name="yohou">午後から80%の確率で雨が予想されています。</p>
</x-card>
ブラウザには以下のように表示される
お知らせ
明日は雨です。傘を持ってください。 // これが $slot の中身
午後から80%の確率で雨が予想されています。 // これが $yohou(名前付きスロット) の中身
以上