【Laravel】簡単アプリ作製【8】Bootstrapで共通テンプレート化とオシャレに装飾

Laravel

 

初期の未装飾なHTML状態から、Bootstrap 5(CDN)を導入して管理画面(CRUD)のUIをモダンに刷新する。 同時に、Bladeの継承機能(@extends)を用いて、ヘッダーやログアウト機能、メッセージ表示などの共通コンポーネントを共通レイアウトファイルへ分離・集約する。

🛠️ 実装の設計方針とコードの連動構造

 いきなり全体のコードを追う前に、今回導入する「共通レイアウト」と「各画面」がどのようにデータをやり取りし、連動しているのかの構造を整理する。

 ┌──────────────────────────────────────┐
 │ [共通レイアウト]  layouts/app.blade.php                                    │
 │                                                                            │
 │  📁 <head> (Bootstrap 5 CSSをCDNで一括読み込み)                            │
 │  📱 navbar (共通ヘッダー:ログイン名 & ログアウトボタン)                  │
 │  🔔 alert  (保存・削除時の成功メッセージ表示エリア)                        │
 │                                                                            │
 │                ┌───────────────────┐                  │
 │                │  @yield('content')                   │ 💻はめ込み       │
 └────────┼───────────────────┼─────────┘
                   ▲                                      ▲
 ┌────────┴────────┐  ┌────────┴────────┐
 │ products/index                   │  │ products/create                  │
 │ (一覧のテーブル)                 │  │ (登録のフォーム)                 │
 └─────────────────┘  └─────────────────┘

1. 共通化のキーとなるBlade構文

  • @yield('パーツ名', 'デフォルト値'):共通側に記述する。「ここに各画面固有の中身を流し込む」ための空き部屋(プレースホルダー)
  • @extends('レイアウト名'):子画面側に記述する。「この画面は指定した共通の枠組み(外枠)を使います」という宣言。
  • @section('パーツ名')@endsection:子画面側に記述する。共通側の @yield で指定した空き部屋に、具体的なHTML(テーブルやフォーム)を流し込む。

2. UIを整えるBootstrap 5の主要クラス

  • container:左右に程よい余白を持たせ、コンテンツを中央寄せにする。
  • card shadow-sm border-0:うっすらと影のついた、境界線のない白い立体的なボックスを作る。フォームやテーブルの土台に最適。
  • table table-hover align-middle:セルの余白を整え、行の縦中央揃えを行い、さらにマウスホバーで背景色が変わるモダンな表にする。
  • form-control / form-select:入力ボックスやセレクトボックスを横幅いっぱいに広げ、フォーカス時に綺麗な青い枠線が出るようにする。

ステップ 1:共通レイアウト(外枠)の作成

 resources/views/layouts/app.blade.php を新規作成する。 全画面で共通して使う「Bootstrapの読み込み」「黒いヘッダー(ログアウトボタン内蔵)」「成功メッセージの通知枠」をここに集約する。

HTML
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!-- 各子画面の @section('title') で指定された文字列がここに入ります -->
    <title>@yield('title', '商品管理システム')</title>
    
    <!-- 🌟 Bootstrap 5 CDN (CSS) をネット経由で一括読み込み -->
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body class="bg-light"> <!-- bg-lightで画面全体を少しグレーにして白カードを引き立たせる -->

    <!-- 📱 共通ナビゲーションバー(ヘッダー) -->
    <nav class="navbar navbar-expand-lg navbar-dark bg-dark mb-4 shadow-sm">
        <div class="container">
            <a class="navbar-brand fw-bold" href="{{ route('products.index') }}">📦 商品管理システム</a>
            
            <!-- 認証状態チェック:ログイン時のみ右側にユーザー名とログアウトボタンを表示 -->
            @auth
            <div class="navbar-nav ms-auto align-items-center text-white">
                <span class="me-3 small">👤 {{ Auth::user()->name }} さん</span>
                <!-- ログアウトはセキュリティ(不正ログアウト防止)のためPOSTフォームで実行 -->
                <form action="{{ route('logout') }}" method="POST" class="d-inline">
                    @csrf
                    <button type="submit" class="btn btn-sm btn-outline-light">ログアウト</button>
                </form>
            </div>
            @endauth
        </div>
    </nav>

    <!-- 🔔 メインコンテンツ挿入領域 -->
    <main class="container">
        <!-- セッションにsuccess(登録・削除完了などのメッセージ)があれば自動で共通表示 -->
        @if (session('success'))
            <div class="alert alert-success alert-dismissible fade show shadow-sm" role="alert">
                {{ session('success') }}
                <!-- 閉じるボタン(JavaScriptで動作) -->
                <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
            </div>
        @endif

        <!-- 🌟 ここに各子画面の @section('content') の中身がガチャンとはめ込まれます -->
        @yield('content')
    </main>

    <!-- 🌟 Bootstrap 5 の動的コンポーネント(アラートの閉じるボタンなど)を動かすための JavaScript -->
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

ステップ 2:商品一覧画面(index)の書き換え

 resources/views/products/index.blade.php の中身を全面刷新する。 無骨なHTMLの表を、Bootstrapのテーブルコンポーネントとカードを使って装飾する。

HTML
<!-- 先ほど作った「layouts/app.blade.php」を共通の外枠として使うことを宣言 -->
@extends('layouts.app')

<!-- 共通枠の @yield('title') に「商品一覧」という文字を送る -->
@section('title', '商品一覧')

<!-- 共通枠の @yield('content') の空き部屋に、以下の中身をすべて流し込む -->
@section('content')
<div class="d-flex justify-content-between align-items-center mb-4">
    <h2 class="fw-bold m-0 text-secondary">商品一覧</h2>
    <!-- btn btn-primary でカチッとした綺麗な青いボタンに変身 -->
    <a href="{{ route('products.create') }}" class="btn btn-primary shadow-sm">➕ 新規登録</a>
</div>

<!-- cardクラスで立体的な白い外枠を作り、その中にテーブルを配置する -->
<div class="card shadow-sm border-0">
    <div class="card-body p-0">
        <div class="table-responsive">
            <!-- table-hover: マウスを乗せた行が薄いグレーになるエフェクト -->
            <table class="table table-hover align-middle m-0">
                <thead class="table-dark"> <!-- ヘッダー行を黒にして引き締める -->
                    <tr>
                        <th class="ps-3" style="width: 80px;">ID</th>
                        <th>商品名</th>
                        <th>カテゴリ</th>
                        <th>価格</th>
                        <th class="pe-3 text-center" style="width: 160px;">操作</th>
                    </tr>
                </thead>
                <tbody>
                    @forelse ($products as $product)
                        <tr>
                            <td class="ps-3 text-muted fw-bold">{{ $product->id }}</td>
                            <td class="fw-bold text-dark">{{ $product->name }}</td>
                            <td>
                                <!-- badgeクラスでカテゴリ名をラベル風(丸角タブ風)に装飾 -->
                                <span class="badge bg-secondary px-2 py-1">
                                    {{ $product->category?->name ?? '未分類' }}
                                </span>
                            </td>
                            <td class="text-success fw-bold">¥{{ number_format($product->price) }}</td>
                            <td class="pe-3 text-center">
                                <!-- btn-group で編集と削除のボタンを隙間なく1つの塊に結合 -->
                                <div class="btn-group btn-group-sm" role="group">
                                    <a href="{{ route('products.edit', $product->id) }}" class="btn btn-outline-primary">編集</a>
                                    
                                    <!-- 削除用フォーム(JavaScript確認ダイアログに動的な商品名「{{ $product->name }}」を埋め込み) -->
                                    <form action="{{ route('products.destroy', $product->id) }}" method="POST" onsubmit="return confirm('「{{ $product->name }}」を削除してもよろしいですか?');" class="d-inline">
                                        @csrf
                                        @method('DELETE')
                                        <button type="submit" class="btn btn-outline-danger">削除</button>
                                    </form>
                                </div>
                            </td>
                        </tr>
                    @empty
                        <tr>
                            <td colspan="5" class="text-center text-muted py-4">登録されている商品はありません。</td>
                        </tr>
                    @endforelse
                </tbody>
            </table>
        </div>
    </div>
</div>
@endsection

ステップ 3:商品登録・編集画面(create / edit)の書き換え

 入力フォーム周りは画面中央にすっきり収まるよう横幅を制限(col-md-8)し、カードフォームの中にBootstrapの各種パーツを適応させる。

商品登録画面(resources/views/products/create.blade.php)

HTML
@extends('layouts.app')

@section('title', '商品登録')

@section('content')
<div class="row justify-content-center"> <!-- フォームを画面のパーツ中央に寄せる -->
    <div class="col-md-8">
        <div class="d-flex align-items-center mb-3">
            <a href="{{ route('products.index') }}" class="btn btn-sm btn-outline-secondary me-3">⬅ 一覧へ戻る</a>
            <h3 class="fw-bold m-0 text-secondary">商品新規登録</h3>
        </div>

        <!-- バリデーションエラーが起きた場合の警告ボックス -->
        @if ($errors->any())
            <div class="alert alert-danger shadow-sm">
                <ul class="mb-0">
                    @foreach ($errors->all() as $error)
                        <li>{{ $error }}</li>
                    @endforeach
                </ul>
            </div>
        @endif

        <!-- カード型の入力フォームコンテナ -->
        <div class="card shadow-sm border-0">
            <div class="card-body p-4">
                <form action="{{ route('products.store') }}" method="POST">
                    @csrf
                    
                    <div class="mb-3">
                        <label for="category_id" class="form-label fw-bold small">カテゴリ</label>
                        <!-- form-select: Bootstrap標準の綺麗なドロップダウンメニュー -->
                        <select name="category_id" id="category_id" class="form-select">
                            <option value="">-- カテゴリを選択してください --</option>
                            @foreach ($categories as $category)
                                <option value="{{ $category->id }}" {{ old('category_id') == $category->id ? 'selected' : '' }}>
                                    [{{ $category->major_category_name }}] {{ $category->name }}
                                </option>
                            @endforeach
                        </select>
                    </div>
                    
                    <div class="mb-3">
                        <label for="name" class="form-label fw-bold small">商品名</label>
                        <!-- form-control: フォーカス時にうっすら青く光るスタイリッシュな入力欄 -->
                        <input type="text" name="name" id="name" class="form-control" value="{{ old('name') }}" placeholder="例: プレミアムコーヒー豆">
                    </div>
                    
                    <div class="mb-3">
                        <label for="price" class="form-label fw-bold small">価格(円)</label>
                        <!-- input-group: 頭に「¥」などの単位マークを合体させるフォームパーツ -->
                        <div class="input-group">
                            <span class="input-group-text">¥</span>
                            <input type="number" name="price" id="price" class="form-control" value="{{ old('price') }}" placeholder="1500">
                        </div>
                    </div>
                    
                    <div class="mb-4">
                        <label for="description" class="form-label fw-bold small">商品説明文</label>
                        <textarea name="description" id="description" class="form-control" rows="4" placeholder="商品の詳細な説明を入力してください">{{ old('description') }}</textarea>
                    </div>
                    
                    <!-- d-grid: 横幅いっぱいに広がる押しやすい大型ボタンを設置 -->
                    <div class="d-grid">
                        <button type="submit" class="btn btn-primary btn-lg shadow-sm fw-bold">商品を登録する</button>
                    </div>
                </form>
            </div>
        </div>
    </div>
</div>
@endsection

商品編集画面(resources/views/products/edit.blade.php)

 基本構造は登録画面と同じ。送信メソッドの疑似指定(@method('PUT'))と、既存データの初期値読み込み(old('name', $product->name))を行う。

HTML
@extends('layouts.app')

@section('title', '商品編集')

@section('content')
<div class="row justify-content-center">
    <div class="col-md-8">
        <div class="d-flex align-items-center mb-3">
            <a href="{{ route('products.index') }}" class="btn btn-sm btn-outline-secondary me-3">⬅ キャンセル</a>
            <h3 class="fw-bold m-0 text-secondary">商品情報編集</h3>
        </div>

        @if ($errors->any())
            <div class="alert alert-danger shadow-sm">
                <ul class="mb-0">
                    @foreach ($errors->all() as $error)
                        <li>{{ $error }}</li>
                    @endforeach
                </ul>
            </div>
        @endif

        <div class="card shadow-sm border-0">
            <div class="card-body p-4">
                <form action="{{ route('products.update', $product->id) }}" method="POST">
                    @csrf
                    @method('PUT') <!-- HTMLフォームでPUT(更新)をシミュレート -->
                    
                    <div class="mb-3">
                        <label for="category_id" class="form-label fw-bold small">カテゴリ</label>
                        <select name="category_id" id="category_id" class="form-select">
                            @foreach ($categories as $category)
                                <option value="{{ $category->id }}" {{ old('category_id', $product->category_id) == $category->id ? 'selected' : '' }}>
                                    [{{ $category->major_category_name }}] {{ $category->name }}
                                </option>
                            @endforeach
                        </select>
                    </div>
                    
                    <div class="mb-3">
                        <label for="name" class="form-label fw-bold small">商品名</label>
                        <input type="text" name="name" id="name" class="form-control" value="{{ old('name', $product->name) }}">
                    </div>
                    
                    <div class="mb-3">
                        <label for="price" class="form-label fw-bold small">価格(円)</label>
                        <div class="input-group">
                            <span class="input-group-text">¥</span>
                            <input type="number" name="price" id="price" class="form-control" value="{{ old('price', $product->price) }}">
                        </div>
                    </div>
                    
                    <div class="mb-4">
                        <label for="description" class="form-label fw-bold small">商品説明文</label>
                        <textarea name="description" id="description" class="form-control" rows="4">{{ old('description', $product->description) }}</textarea>
                    </div>
                    
                    <!-- 更新用は目立たせるためにボタンの色を緑色(btn-success)に指定 -->
                    <div class="d-grid">
                        <button type="submit" class="btn btn-success btn-lg shadow-sm fw-bold">変更を保存する</button>
                    </div>
                </form>
            </div>
        </div>
    </div>
</div>
@endsection

📌 導入後の動作確認・検証のチェックポイント

すべてのファイルを配置したあと、ブラウザで /products(一覧画面)にアクセスし、以下の挙動が正常に動作しているか確認する。

1.レイアウトが共通化されているか
 一覧・登録・編集のどの画面を開いても、上部の「黒いナビゲーションバー(ヘッダー)」が共通して崩れずに固定表示されているか。
 右上に現在ログインしているユーザー名が正しく出力されているか。

2.Bootstrapの各クラスが機能しているか
 テーブルの行にマウスを当てた際、背景色が薄いグレーに反応するか(table-hoverの検証)。
 入力フォームを1クリックした際、枠線が綺麗な青色に変化するか(form-controlの検証)。

3.通知メッセージとJavaScriptが連動しているか

 商品を追加・変更・削除した際、一覧画面の上部に緑色の通知アラート(alert-success)が表示され、その右端の「×」を押すと、JavaScriptによってパッと消えるか。

 削除ボタンを押した際、「〇〇(その行の商品名)を削除してもよろしいですか?」というブラウザ標準のダイアログが正しくポップアップするか。

初期の未装飾なHTML状態から、Bootstrap 5(CDN)を導入して管理画面(CRUD)のUIをモダンに刷新する。
 同時に、Bladeの継承機能(@extends)を用いて、ヘッダーやログアウトボタン、メッセージ表示などの共通コンポーネントを共通レイアウトファイルへ分離・集約する。

1.実装の全体構造・設計方針

1. テンプレートの共通化(共通枠と中身の分離)

 各画面(一覧・登録・編集)で重複していた <html>, <head>, 認証状態に応じた「ヘッダー(ログアウト機能)」などの記述を、1つの共通レイアウトファイルに集約する。

  • 共通レイアウト(外枠): resources/views/layouts/app.blade.php Bootstrapの読み込み、ナビゲーションバー(ログアウトボタン)、フラッシュメッセージ(成功通知)の表示エリアを定義。コンテンツ挿入位置に @yield('content') を配置。
  • 各ビュー(中身): 一覧(index)、登録(create)、編集(edit) 先頭で @extends('layouts.app') を宣言し、@section('content')@endsection の中に固有のUIコード(テーブルやフォーム)のみを記述する。

2. Bootstrap 5の主要クラス適用

  • table table-hover: ホバーエフェクト付きのレスポンシブなデータテーブル
  • card shadow-sm: 境界線を排した立体感のあるフォーム用白背景コンテナ
  • form-control form-select: 横幅いっぱいに広がるモダンな入力フィールド
  • btn btn-primary / btn-success: 視認性の高いフラットデザインボタン

ステップ 1:共通レイアウトの作成

resources/views/layouts/app.blade.php を新規作成し、全体のベースとなる外枠を実装する。

HTML
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@yield('title', '商品管理システム')</title>
    <!-- Bootstrap 5 CDN (CSS) -->
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body class="bg-light">

    <!-- 共通ナビゲーションバー(ヘッダー) -->
    <nav class="navbar navbar-expand-lg navbar-dark bg-dark mb-4 shadow-sm">
        <div class="container">
            <a class="navbar-brand fw-bold" href="{{ route('products.index') }}">📦 商品管理システム</a>
            
            <!-- 認証状態チェック:ログイン時のみ右側にユーザー名とログアウトボタンを表示 -->
            @auth
            <div class="navbar-nav ms-auto align-items-center text-white">
                <span class="me-3 small">👤 {{ Auth::user()->name }} さん</span>
                <form action="{{ route('logout') }}" method="POST" class="d-inline">
                    @csrf
                    <button type="submit" class="btn btn-sm btn-outline-light">ログアウト</button>
                </form>
            </div>
            @endauth
        </div>
    </nav>

    <!-- メインコンテンツ挿入領域 -->
    <main class="container">
        <!-- グリントメッセージ(セッション経由の成功通知)の共通表示 -->
        @if (session('success'))
            <div class="alert alert-success alert-dismissible fade show shadow-sm" role="alert">
                {{ session('success') }}
                <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
            </div>
        @endif

        @yield('content')
    </main>

    <!-- Bootstrap 5 CDN (JavaScript) -->
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

ステップ 2:商品一覧画面(index)の書き換え

resources/views/products/index.blade.php の中身を全面刷新。テーブル、バッジ、ボタングループの装飾を適用。

HTML
@extends('layouts.app')

@section('title', '商品一覧')

@section('content')
<div class="d-flex justify-content-between align-items-center mb-4">
    <h2 class="fw-bold m-0 text-secondary">商品一覧</h2>
    <a href="{{ route('products.create') }}" class="btn btn-primary shadow-sm">➕ 新規登録</a>
</div>

<div class="card shadow-sm border-0">
    <div class="card-body p-0">
        <div class="table-responsive">
            <table class="table table-hover align-middle m-0">
                <thead class="table-dark">
                    <tr>
                        <th class="ps-3" style="width: 80px;">ID</th>
                        <th>商品名</th>
                        <th>カテゴリ</th>
                        <th>価格</th>
                        <th class="pe-3 text-center" style="width: 160px;">操作</th>
                    </tr>
                </thead>
                <tbody>
                    @forelse ($products as $product)
                        <tr>
                            <td class="ps-3 text-muted fw-bold">{{ $product->id }}</td>
                            <td class="fw-bold text-dark">{{ $product->name }}</td>
                            <td>
                                <span class="badge bg-secondary px-2 py-1">
                                    {{ $product->category?->name ?? '未分類' }}
                                </span>
                            </td>
                            <td class="text-success fw-bold">¥{{ number_format($product->price) }}</td>
                            <td class="pe-3 text-center">
                                <div class="btn-group btn-group-sm" role="group">
                                    <a href="{{ route('products.edit', $product->id) }}" class="btn btn-outline-primary">編集</a>
                                    
                                    <!-- 削除用フォーム(動的な商品名を含んだJavaScript確認アラート付き) -->
                                    <form action="{{ route('products.destroy', $product->id) }}" method="POST" onsubmit="return confirm('「{{ $product->name }}」を削除してもよろしいですか?');" class="d-inline">
                                        @csrf
                                        @method('DELETE')
                                        <button type="submit" class="btn btn-outline-danger">削除</button>
                                    </form>
                                </div>
                            </td>
                        </tr>
                    @empty
                        <tr>
                            <td colspan="5" class="text-center text-muted py-4">登録されている商品はありません。</td>
                        </tr>
                    @endforelse
                </tbody>
            </table>
        </div>
    </div>
</div>
@endsection

ステップ 3:商品登録・編集画面(create / edit)の書き換え

フォームコンポーネント、バリデーションエラー表示をBootstrapスタイルに適応させる。

商品登録画面(resources/views/products/create.blade.php)

HTML
@extends('layouts.app')

@section('title', '商品登録')

@section('content')
<div class="row justify-content-center">
    <div class="col-md-8">
        <div class="d-flex align-items-center mb-3">
            <a href="{{ route('products.index') }}" class="btn btn-sm btn-outline-secondary me-3">⬅ 一覧へ戻る</a>
            <h3 class="fw-bold m-0 text-secondary">商品新規登録</h3>
        </div>

        @if ($errors->any())
            <div class="alert alert-danger shadow-sm">
                <ul class="mb-0">
                    @foreach ($errors->all() as $error)
                        <li>{{ $error }}</li>
                    @endforeach
                </ul>
            </div>
        @endif

        <div class="card shadow-sm border-0">
            <div class="card-body p-4">
                <form action="{{ route('products.store') }}" method="POST">
                    @csrf
                    
                    <div class="mb-3">
                        <label for="category_id" class="form-label fw-bold small">カテゴリ</label>
                        <select name="category_id" id="category_id" class="form-select">
                            <option value="">-- カテゴリを選択してください --</option>
                            @foreach ($categories as $category)
                                <option value="{{ $category->id }}" {{ old('category_id') == $category->id ? 'selected' : '' }}>
                                    [{{ $category->major_category_name }}] {{ $category->name }}
                                </option>
                            @endforeach
                        </select>
                    </div>
                    
                    <div class="mb-3">
                        <label for="name" class="form-label fw-bold small">商品名</label>
                        <input type="text" name="name" id="name" class="form-control" value="{{ old('name') }}" placeholder="例: プレミアムコーヒー豆">
                    </div>
                    
                    <div class="mb-3">
                        <label for="price" class="form-label fw-bold small">価格(円)</label>
                        <div class="input-group">
                            <span class="input-group-text">¥</span>
                            <input type="number" name="price" id="price" class="form-control" value="{{ old('price') }}" placeholder="1500">
                        </div>
                    </div>
                    
                    <div class="mb-4">
                        <label for="description" class="form-label fw-bold small">商品説明文</label>
                        <textarea name="description" id="description" class="form-control" rows="4" placeholder="商品の詳細な説明を入力してください">{{ old('description') }}</textarea>
                    </div>
                    
                    <div class="d-grid">
                        <button type="submit" class="btn btn-primary btn-lg shadow-sm fw-bold">商品を登録する</button>
                    </div>
                </form>
            </div>
        </div>
    </div>
</div>
@endsection

商品編集画面(resources/views/products/edit.blade.php)

HTML
@extends('layouts.app')

@section('title', '商品編集')

@section('content')
<div class="row justify-content-center">
    <div class="col-md-8">
        <div class="d-flex align-items-center mb-3">
            <a href="{{ route('products.index') }}" class="btn btn-sm btn-outline-secondary me-3">⬅ キャンセル</a>
            <h3 class="fw-bold m-0 text-secondary">商品情報編集</h3>
        </div>

        @if ($errors->any())
            <div class="alert alert-danger shadow-sm">
                <ul class="mb-0">
                    @foreach ($errors->all() as $error)
                        <li>{{ $error }}</li>
                    @endforeach
                </ul>
            </div>
        @endif

        <div class="card shadow-sm border-0">
            <div class="card-body p-4">
                <form action="{{ route('products.update', $product->id) }}" method="POST">
                    @csrf
                    @method('PUT')
                    
                    <div class="mb-3">
                        <label for="category_id" class="form-label fw-bold small">カテゴリ</label>
                        <select name="category_id" id="category_id" class="form-select">
                            @foreach ($categories as $category)
                                <option value="{{ $category->id }}" {{ old('category_id', $product->category_id) == $category->id ? 'selected' : '' }}>
                                    [{{ $category->major_category_name }}] {{ $category->name }}
                                </option>
                            @endforeach
                        </select>
                    </div>
                    
                    <div class="mb-3">
                        <label for="name" class="form-label fw-bold small">商品名</label>
                        <input type="text" name="name" id="name" class="form-control" value="{{ old('name', $product->name) }}">
                    </div>
                    
                    <div class="mb-3">
                        <label for="price" class="form-label fw-bold small">価格(円)</label>
                        <div class="input-group">
                            <span class="input-group-text">¥</span>
                            <input type="number" name="price" id="price" class="form-control" value="{{ old('price', $product->price) }}">
                        </div>
                    </div>
                    
                    <div class="mb-4">
                        <label for="description" class="form-label fw-bold small">商品説明文</label>
                        <textarea name="description" id="description" class="form-control" rows="4">{{ old('description', $product->description) }}</textarea>
                    </div>
                    
                    <div class="d-grid">
                        <button type="submit" class="btn btn-success btn-lg shadow-sm fw-bold">変更を保存する</button>
                    </div>
                </form>
            </div>
        </div>
    </div>
</div>
@endsection

コメント