【Laravel】簡単アプリ作製【3】 商品追加機能

Laravel

作成済みのカテゴリと紐付いた、商品の追加機能(マイグレーション・モデル・コントローラー・ビュー)を実装する手順。

1. シーダーの修正(外部キー制約エラー対策)

商品テーブル(子)から参照されているため、そのままクリアしようとするとエラーになります。一時的に外部キーチェックを無効化するコードを追加します。
database/seeders/CategorySeeder.php

PHP
<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;
use App\Models\Category;
use App\Models\Product;             // ★追加:Productモデルのインポート
use Illuminate\Support\Facades\DB; // ★追加:DBファサードのインポート

class CategorySeeder extends Seeder
{
    public function run(): void
    {
        // ★追加:外部キーチェックを一時的に無効化
        DB::statement('SET FOREIGN_KEY_CHECKS=0;');

        // ★追加・変更:子テーブルと親テーブルの両方を安全にクリア
        Product::truncate(); 
        Category::truncate();

        // ★追加:外部キーチェックを有効化に戻す
        DB::statement('SET FOREIGN_KEY_CHECKS=1;');

        // ダミーデータの追加(ここからは変更なし)
        Category::create([
            'name' => '',
            'description' => 'ビジネス書、小説、マンガなどを含みます。',
            'major_category_name' => 'エンタメ',
        ]);

        Category::create([
            'name' => 'パソコン',
            'description' => 'ノートPC、デスクトップPC、周辺機器など。',
            'major_category_name' => '家電・IT',
        ]);
    }
}

2. 商品機能の土台作成(マイグレーションとモデル)

Step 1: Artisanコマンドの実行

商品のモデル・マイグレーション・コントローラーを一括生成する。

PowerShell
PS C:\xampp\htdocs\laravel-app> php artisan make:model Product -mc

Step 2: テーブル定義(マイグレーションファイルの編集)

up メソッド内に、商品名、商品説明、価格、そしてカテゴリと紐付けるための外部キーを追記する。
database/migrations/xxxx_xx_xx_xxxxxx_create_products_table.php

PHP
public function up(): void
{
    Schema::create('products', function (Blueprint $table) {
        $table->id();
        // 追加:カテゴリテーブルとの紐付け(カテゴリが消えたら商品も消える設定)
        $table->foreignId('category_id')->constrained()->cascadeOnDelete(); 
        $table->string('name');        // 追加:商品名
        $table->text('description');   // 追加:商品説明文
        $table->integer('price');      // 追加:価格
        $table->timestamps();
    });
}

Step 3: モデルの編集

一括保存を許可するカラム($fillable)を指定する。
app/Models/Product.php

PHP
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo; // // 追加:リレーション用のインポート

class Product extends Model
{
    use HasFactory;

    // 追加:保存を許可するカラムを指定
    protected $fillable = [
        'category_id',
        'name',
        'description',
        'price',
    ];
    
  // // 追加:カテゴリモデルとの紐づけ(1対多の「1」側)
    public function category(): BelongsTo
    {
        return $this->belongsTo(Category::class);
    }
}

Step 4: カテゴリモデルへのリレーション定義

カテゴリ側からも所属する商品一覧を引っ張れるよう、既存のカテゴリモデルに商品モデルとのリレーション(紐づけ)を追記して保存します。
app/Models/Category.php

PHP
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany; // // 追加:リレーション用のインポート

class Category extends Model
{
    use HasFactory;

    protected $fillable = [
        'name',
        'description',
        'major_category_name',
    ];

    // // 追加:商品モデルとの紐づけ(1対多の「多」側)
    public function products(): HasMany
    {
        return $this->hasMany(Product::class);
    }
}

3. 商品追加処理(ルーティング・コントローラー・ビュー)の実装

Step 1: ルーティングの設定

routes/web.php

PHP
<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\CategoryController;
use App\Http\Controllers\ProductController; // ★追加:商品コントローラーのインポート

// 追加:商品機能のルーティング
Route::get('/products/create', [ProductController::class, 'create'])->name('products.create');
Route::post('/products', [ProductController::class, 'store'])->name('products.store');

Step 2: コントローラーの編集

app/Http/Controllers/ProductController.php

PHP
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Category; // ★追加:カテゴリを選択させるために必要
use App\Models\Product;  // ★追加:商品保存に必要

class ProductController extends Controller
{
    // 追加:商品登録画面の表示
    public function create()
    {
        // 登録フォームのセレクトボックス用に、全カテゴリを取得して画面に渡す
        $categories = Category::all();
        return view('products.create', compact('categories'));
    }

    // 追加:商品の保存処理
    public function store(Request $request)
    {
        // 入力チェック
        $request->validate([
            'category_id' => 'required|exists:categories,id', // カテゴリが存在するかチェック
            'name' => 'required|max:100',
            'description' => 'required',
            'price' => 'required|integer|min:0', // 0以上の整数かチェック
        ]);

        // データベースへ保存
        Product::create([
            'category_id' => $request->category_id,
            'name' => $request->name,
            'description' => $request->description,
            'price' => $request->price,
        ]);

        return redirect()->back()->with('success', '商品を追加しました。');
    }
}

Step 3: ビュー(画面)の作成

  1. resources/views の中に products フォルダを新規作成 する。
  2. 作成したフォルダの中に create.blade.php ファイルを新規作成 する。
  3. 作成したファイルに、カテゴリ選択(セレクトボックス)を含む以下のHTMLコードを記述して保存する。
    resources/views/products/create.blade.php
HTML
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>商品追加</title>
</head>
<body>
    <h1>商品新規追加</h1>

    @if (session('success'))
        <p style="color: green;">{{ session('success') }}</p>
    @endif

    @if ($errors->any())
        <ul style="color: red;">
            @foreach ($errors->all() as $error)
                <li>{{ $error }}</li>
            @endforeach
        </ul>
    @endif

    <form action="{{ route('products.store') }}" method="POST">
        @csrf
        
        <div>
            <label for="category_id">カテゴリ:</label>
            <select name="category_id" id="category_id">
                <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>
        <br>
        
        <div>
            <label for="name">商品名:</label>
            <input type="text" name="name" id="name" value="{{ old('name') }}">
        </div>
        <br>
        
        <div>
            <label for="price">価格:</label>
            <input type="number" name="price" id="price" value="{{ old('price') }}">
        </div>
        <br>
        
        <div>
            <label for="description">商品説明文:</label>
            <textarea name="description" id="description">{{ old('description') }}</textarea>
        </div>
        <br>
        
        <button type="submit">商品を追加する</button>
    </form>
</body>
</html>

4. データベースの更新

新しい products テーブルを作成するため、マイグレーションを実行する。 ※前回のシーダー(CategorySeeder)をそのまま残して初期データを入れたい場合は、以下のコマンドで一発でテーブルが再生成され、商品登録に必要なカテゴリデータが自動で入る。

PowerShell
PS C:\xampp\htdocs\laravel-app> php artisan migrate:fresh --seed

5. 動作確認(XAMPP環境)

1.XAMPPのApacheとMySQLが起動していることを確認。

2.ブラウザを開き、以下のURLへ直接アクセスする。
  http://localhost/laravel-app/public/products/create

3.セレクトボックスに、シーダーで入れたカテゴリ(「本」や「パソコン」)が自動で表示されていることを確認する。

4.商品名・価格・説明文を入力して送信し、エラーなく登録でき、phpMyAdminの products テーブルにデータが入っていれば完了。

※この記事はAIで生成後、実際に手順通り実施して加筆、修正しています。

コメント