0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

コンポーネントとslot - Laravel学習 #2

0
Last updated at Posted at 2026-05-20

Laravel初学者による学習のまとめ #2

#1はこちら

コンポーネント

<x-guest-layout> のように書くことでコンポーネントが使える。

  • resources/views/components/配下
    クラスを使わない時
    匿名コンポーネントと呼ばれる
<div>
    <div>
        {{ $trigger }}
    </div>
</div>
  • app/View/Components/配下
    クラスを使う時
    クラスコンポーネントと呼ばれる
resources/views/dashboad.blade.php
<!-- この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>
app/Views/Compornents/AppLayout.php
<?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を使っている
    }
}
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を使う
    }
}
layouts/app.blade.php
こんにちは{{ $user->name }} さん

このようにデータをフロントに渡すことができる

slot

{{ $slot }} は、親ページがコンポーネントに渡した「本文の HTML」が入る場所。

枠(レイアウト)の真ん中に、ページごとの中身を差し込むための「穴」のようなもの。

子. 枠を作る

resources/views/components/card.blade.php
<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 }などのように任意のスロット名をつけられる。

resources/views/components/card.blade.php
<div>
    <p>お知らせ</p>
    <div>
        {{ $slot }}
    </div>
    <div>
        {{ $yohou }}
    </div>
    <p>以上</p>
</div>
<x-card>

    明日は雨です傘を持ってください
    
    <p name="yohou">午後から80の確率で雨が予想されています</p>
    
</x-card>

ブラウザには以下のように表示される

 お知らせ                 

 明日は雨です傘を持ってください    // これが $slot の中身

 午後から80の確率で雨が予想されています。 // これが $yohou(名前付きスロット) の中身

 以上                     
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?