#05 Laravel基礎

Bladeコンポーネントを使いこなす

Bladeの復習と次のステップ

基礎シリーズでは @if, @foreach, @extends, @yield を学びました。このシリーズでは再利用可能なUI部品を作るための Bladeコンポーネント? HTMLの部品をクラスまたはファイルとして切り出す仕組み。`<x-button>`のように使える再利用可能なUI部品を作れる。 と、より高度なテンプレート技術を扱います。


匿名コンポーネント(ファイルだけで作る)

最もシンプルなBladeコンポーネントは、resources/views/components/ にBladeファイルを置くだけで作れます。

# components フォルダを作成し、ファイルを配置
# (コマンドでの自動生成もできる)
php artisan make:component Alert --view

resources/views/components/alert.blade.php が生成されます。

{{-- 📁 resources/views/components/alert.blade.php --}}
<div class="alert alert-{{ $type ?? 'info' }}">
    {{ $slot }}
</div>

呼び出し方

{{-- 📁 resources/views/posts/index.blade.php --}}

<x-alert type="success">
    投稿を保存しました!
</x-alert>

<x-alert type="danger">
    エラーが発生しました。
</x-alert>

<x-コンポーネント名> のタグで呼び出せます。タグの中身が $slot に渡されます。


クラスを持つコンポーネント

ロジックが必要なコンポーネントはクラスとセットで作ります。

php artisan make:component UserCard

2つのファイルが生成されます。

<?php
// 📁 app/View/Components/UserCard.php

namespace App\View\Components;

use App\Models\User;
use Illuminate\View\Component;

class UserCard extends Component
{
    public function __construct(
        public User $user  // ← ビューに自動で渡される
    ) {}

    public function render()
    {
        return view('components.user-card');
    }
}
{{-- 📁 resources/views/components/user-card.blade.php --}}
<div class="user-card">
    <img src="{{ $user->avatar_url }}" alt="{{ $user->name }}">
    <h3>{{ $user->name }}</h3>
    <p>{{ $user->email }}</p>
</div>

呼び出すときはモデルを渡します。

{{-- 📁 resources/views/users/index.blade.php --}}

@foreach ($users as $user)
    <x-user-card :user="$user" />
@endforeach

:user="$user" のように : を付けると PHP の変数を渡せます。


名前付きスロット

$slot は1つだけですが、名前付きスロットを使うと複数の差し込み口を作れます。

{{-- 📁 resources/views/components/card.blade.php --}}
<div class="card">
    <div class="card-header">
        {{ $header }}  {{-- 名前付きスロット --}}
    </div>
    <div class="card-body">
        {{ $slot }}    {{-- デフォルトスロット --}}
    </div>
    <div class="card-footer">
        {{ $footer ?? '' }}  {{-- 省略可能なスロット --}}
    </div>
</div>
{{-- 使い方 --}}
<x-card>
    <x-slot:header>
        <h2>投稿一覧</h2>
    </x-slot:header>

    {{-- ここがデフォルト $slot --}}
    <p>投稿内容がここに入ります。</p>
</x-card>

@stack と @push でスクリプトを整理する

ページごとに追加したい CSS や JavaScript を、レイアウトの特定の場所にまとめて出力する仕組みです。

レイアウトに @stack を定義します。

{{-- 📁 resources/views/layouts/app.blade.php --}}
<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" href="/css/app.css">
    @stack('styles')  {{-- ← ページごとのCSSをここに出力 --}}
</head>
<body>
    @yield('content')
    <script src="/js/app.js"></script>
    @stack('scripts')  {{-- ← ページごとのJSをここに出力 --}}
</body>
</html>

子ビューから @push で追加します。

{{-- 📁 resources/views/posts/edit.blade.php --}}
@extends('layouts.app')

@push('styles')
    <link rel="stylesheet" href="/css/editor.css">
@endpush

@section('content')
    <div id="editor">...</div>
@endsection

@push('scripts')
    <script src="/js/editor.js"></script>
@endpush

カスタムディレクティブ

@if, @foreach のような独自の @xxx ディレクティブを作れます。

// 📁 app/Providers/AppServiceProvider.php

use Illuminate\Support\Facades\Blade;

public function boot(): void
{
    // @admin〜@endadmin : 管理者だけ表示するディレクティブ
    Blade::directive('admin', function () {
        return "<?php if(auth()->check() && auth()->user()->role === 'admin'): ?>";
    });

    Blade::directive('endadmin', function () {
        return "<?php endif; ?>";
    });
}

使い方:

@admin
    <a href="/admin/dashboard">管理画面へ</a>
@endadmin

まとめ

  • resources/views/components/ にファイルを置くだけで匿名コンポーネントが作れる
  • <x-コンポーネント名> で呼び出す
  • クラス付きコンポーネントはロジックをPHPクラスに書ける
  • @stack / @push でページごとのCSS・JSを整理できる
  • Blade::directive() でカスタムディレクティブを定義できる

次回はEloquentのリレーションを深掘りします。