【Laravel】Seeder完全ガイド|作成・実行・Factory連携から本番運用の注意点まで

Laravel入門実装・応用テクニック

Laravelでデータベースに初期データやテスト用ダミーデータを一括投入したいときに欠かせないのがSeeder(シーダー)です。

基本実行は php artisan db:seedphp artisan db:seed --class=Seeder名 コマンド1つで行えますが、実務では「Factoryとどう連携してダミーデータを自動生成するか」「本番環境で安全にマスタデータだけを投入するにはどう設計すべきか」といった運用面まで押さえておく必要があります。

この記事では、LaravelのSeederの基本概念から、作成・書き方(DBファサード/Eloquent/Factory連携/冪等設計)、DatabaseSeederでの環境分岐、実行コマンド一覧、本番運用の注意点、よくあるエラー対処までを網羅して分かりやすく解説します。

  1. LaravelのSeederとは?Migration・Factoryとの役割の違い
    1. Migration / Factory / Seeder の役割分担
  2. Seederファイルの作成方法(make:seeder)
    1. Seeder作成コマンド
    2. Seederの命名規則
    3. 生成されるSeederファイルの初期構造
  3. Seederの具体的な書き方4パターン
    1. パターン1: DBファサード(クエリビルダ)を使う
    2. パターン2: Eloquentモデルを使う
    3. パターン3: Factory連携で大量ダミーデータを生成する(推奨)
    4. パターン4: updateOrCreate / upsert で再実行可能な「冪等性」を持たせる
  4. DatabaseSeederの設計と環境ごとの切り分け
    1. $this->call() による実行順序の制御
    2. 環境(local / production)による投入データの分離
  5. Laravel Seederの実行コマンド一覧と使い分け
    1. 1. 全Seederを実行する(基本)
    2. 2. 特定のSeederだけを単体実行する(開発時に多用)
    3. 3. マイグレーションと同時にSeederを実行する
    4. 4. 本番環境で強制実行する(–force)
  6. 本番環境(Production)でSeederを運用する際の重要注意点
    1. 1. Faker(Factory)の本番依存関係エラーに注意
    2. 2. 冪等性(Idempotency)を徹底する
    3. 3. 実行前のDBバックアップ
    4. 4. 大量データ投入時のバルクインサートとメモリ節約
  7. Seederでよくあるエラーと解決手順(トラブルシューティング)
    1. 1. Class “Database\Seeders\XxxSeeder” not found
    2. 2. db:seedを実行したのにデータが入らない
    3. 3. Cannot add or update a child row: a foreign key constraint fails
    4. 4. Integrity constraint violation: 1062 Duplicate entry
    5. 5. Add [xxx] to fillable property to allow mass assignment
  8. よくある質問(FAQ)
    1. SeederとFactoryはどう使い分けるべき?
    2. Seederの実行結果をロールバック(元に戻す)はできる?
  9. まとめ
  10. 関連記事

LaravelのSeederとは?Migration・Factoryとの役割の違い

Seeder(シーダー)とは、データベースに初期レコードやテスト用データを自動で流し込む(Seed=種をまく)ための仕組みです。

Laravel開発でSeederを活用する主なメリットは次のとおりです。

  • 環境構築の自動化:新しい開発メンバーが参加した際やDockerコンテナを立ち上げた際に、1コマンドで動作確認用データを用意できる
  • テストデータの再現性:手動入力の手間を省き、チーム全員が常に同じ条件のデータで開発・検証を行える
  • マスタデータの確実な投入:都道府県一覧やユーザー権限、初期管理者アカウントなど、アプリの稼働に必須の初期データを安全に登録できる

Migration / Factory / Seeder の役割分担

Laravelのデータベース周辺機能は似た用語が多いため、それぞれの役割を整理しておきましょう。

機能主な役割例え
Migration(マイグレーション)テーブルの作成・カラム定義・インデックス追加など「テーブル構造」を管理するデータベースの「設計図・器」
Factory(ファクトリ)Fakerを利用して氏名・メールアドレスなどの「ダミーデータ」を定義・自動生成するデータの「製造工場」
Seeder(シーダー)Factoryや直接定義したデータを「データベースへ投入する処理・手順」を担うデータを器へ「流し込む作業員」

マイグレーションの基礎については【Laravel】マイグレーション完全ガイド|作成・実行・ロールバック・カラム変更まで徹底解説を、Fakerによるデータ生成はLaravel Fakerを使ったデータ生成の基本と効果的な活用法も合わせて参考にしてください。

Seederファイルの作成方法(make:seeder)

Seederクラスは、Artisanコマンドを使って簡単に生成できます。

Seeder作成コマンド

ターミナルで以下のコマンドを実行します。

php artisan make:seeder UserSeeder

コマンドを実行すると、database/seeders/UserSeeder.php が生成されます。コマンドの詳細はmake:seeder — シーダーの生成コマンドで解説しています。

Seederの命名規則

Seederのクラス名は 対象モデル名(またはテーブル名)+ Seeder(アッパーキャメルケース)にするのが標準的なルールです。

  • UserSeeder(ユーザーテーブル用)
  • PostSeeder(投稿テーブル用)
  • AdminUserSeeder(初期管理者データ用)

生成されるSeederファイルの初期構造

作成された直後のSeederファイルは次のようになっています。

<?php

namespace Database\Seeders;

use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;

class UserSeeder extends Seeder
{
    /**
     * Run the database seeds.
     */
    public function run(): void
    {
        // ここにデータ投入ロジックを記述する
    }
}

Seederが実行されると、この run() メソッド内に書かれたコードが呼び出されます。

Seederの具体的な書き方4パターン

run() メソッド内にデータを投入するコードを書く際、実務では主に4つのアプローチがあります。用途に応じて使い分けましょう。

パターン1: DBファサード(クエリビルダ)を使う

DB::table('テーブル名')->insert(...) を使って直接SQLのINSERT文を発行する方法です。モデルイベントやマスアサインメント(fillable)の影響を受けず、シンプルな初期値投入に適しています。

<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;

class UserSeeder extends Seeder
{
    public function run(): void
    {
        DB::table('users')->insert([
            [
                'name' => '管理者 太郎',
                'email' => 'admin@example.com',
                'password' => Hash::make('password123'),
                'role' => 'admin',
                'created_at' => now(),
                'updated_at' => now(),
            ],
            [
                'name' => '一般 花子',
                'email' => 'user@example.com',
                'password' => Hash::make('password123'),
                'role' => 'general',
                'created_at' => now(),
                'updated_at' => now(),
            ],
        ]);
    }
}

※DBファサードの insert では created_atupdated_at が自動設定されないため、配列内で明示的に now() を指定する必要があります。

パターン2: Eloquentモデルを使う

Eloquentモデルの create() メソッドを使う方法です。タイムスタンプが自動補完され、モデルのミューテタやキャスト機能が有効になります。

<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;
use App\Models\User;
use Illuminate\Support\Facades\Hash;

class UserSeeder extends Seeder
{
    public function run(): void
    {
        User::create([
            'name' => '開発テストユーザー',
            'email' => 'test@example.com',
            'password' => Hash::make('password123'),
        ]);
    }
}

注意点として、モデル側(User.php)で $fillable または $guarded が正しく設定されていないと MassAssignmentException が発生します。

パターン3: Factory連携で大量ダミーデータを生成する(推奨)

開発・テスト環境用で数十〜数百件のダミーデータを用意したい場合、Factory(ファクトリ)と連携するのが最も効率的です。

<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;
use App\Models\User;
use App\Models\Post;

class UserSeeder extends Seeder
{
    public function run(): void
    {
        // 1. ダミーユーザーを50件一括生成
        User::factory()->count(50)->create();

        // 2. リレーションを持たせて生成(各ユーザーに記事を3件ずつ紐付け)
        User::factory()
            ->count(10)
            ->has(Post::factory()->count(3))
            ->create();
    }
}

Factoryを活用することで、Fakerによるリアルなダミー値(名前、住所、本文、日時など)が自動生成され、テストシナリオの検証が格段にスムーズになります。

パターン4: updateOrCreate / upsert で再実行可能な「冪等性」を持たせる

マスタデータ(権限一覧、カテゴリ一覧、固定の設定値など)を投入する際、insertcreate をそのまま使うと、2回目のSeeder実行時に「Duplicate entry(重複エラー)」が発生してしまいます。

何度実行しても同じ安全な状態を保つ(=冪等性(べきとうせい)の確保)ために、updateOrCreate または upsert を利用するのがベストプラクティスです。

<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;
use App\Models\Category;

class CategorySeeder extends Seeder
{
    public function run(): void
    {
        $categories = [
            ['slug' => 'news', 'name' => 'お知らせ'],
            ['slug' => 'tech', 'name' => '技術情報'],
            ['slug' => 'column', 'name' => 'コラム'],
        ];

        foreach ($categories as $data) {
            // slugが一致するレコードがあれば更新、なければ新規作成
            Category::updateOrCreate(
                ['slug' => $data['slug']],
                ['name' => $data['name']]
            );
        }
    }
}

DatabaseSeederの設計と環境ごとの切り分け

個別のSeederを作成したら、親玉となる database/seeders/DatabaseSeeder.php に登録します。

$this->call() による実行順序の制御

外部キー制約が存在する場合、子テーブルのSeederを先に実行すると制約エラーになります。DatabaseSeeder で親テーブルから順番に呼び出すように記述します。

<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    public function run(): void
    {
        $this->call([
            RoleSeeder::class,     // 1. 権限マスタ(親)
            UserSeeder::class,     // 2. ユーザーデータ
            CategorySeeder::class, // 3. カテゴリマスタ(親)
            PostSeeder::class,     // 4. 投稿データ(子)
        ]);
    }
}

環境(local / production)による投入データの分離

本番環境に「テスト用の偽ユーザー」が紛れ込む事故を防ぐため、app()->isLocal()app()->environment() を使って環境ごとに実行するSeederを切り分けるのがプロの現場の鉄則です。

<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    public function run(): void
    {
        // 全環境共通で必要なマスタデータ
        $this->call([
            RoleSeeder::class,
            CategorySeeder::class,
        ]);

        // ローカル開発・テスト環境のみで実行するダミーデータ
        if (app()->isLocal()) {
            $this->call([
                DummyUserSeeder::class,
                DummyPostSeeder::class,
            ]);
        }
    }
}

Laravel Seederの実行コマンド一覧と使い分け

Seederを実行するArtisanコマンドを用途に合わせて整理しました。php artisanの使い方完全ガイドも参考にしてください。

1. 全Seederを実行する(基本)

php artisan db:seed

DatabaseSeederrun() メソッドを実行します。登録されているすべてのSeederが順番に実行されます。コマンド詳細はdb:seed — データベースにシードデータを投入するコマンドを参照してください。

2. 特定のSeederだけを単体実行する(開発時に多用)

php artisan db:seed --class=UserSeeder

--class オプションを指定すると、DatabaseSeeder に登録していないSeederであってもピンポイントで単体実行できます。新規Seederの動作確認や、特定テーブルのみデータを再投入したいときに最適です。

3. マイグレーションと同時にSeederを実行する

# テーブルをすべて削除して再構築した上で、Seederを実行
php artisan migrate:fresh --seed

# 特定のSeederだけを指定してマイグレーションと同時に実行
php artisan migrate:fresh --seed --seeder=UserSeeder

migrate:fresh --seed は、開発中にデータベースを初期状態へリセットしてテストデータを入れ直す際の定番コマンドです(全テーブルがDROPされるため、本番環境では絶対に実行しないでください)。

4. 本番環境で強制実行する(–force)

php artisan db:seed --force

本番環境(APP_ENV=production)では、誤操作を防ぐために「本当に実行しますか?」という確認プロンプトが表示されます。CI/CDパイプラインやデプロイスクリプトなど非対話形式で実行する場合は、--force オプションを付与してプロンプトをスキップします。

本番環境(Production)でSeederを運用する際の重要注意点

本番環境でのSeeder実行は、一度のミスがデータ損失やサービス障害につながる危険性があります。以下の安全対策を必ず確認しておきましょう。

1. Faker(Factory)の本番依存関係エラーに注意

Laravelの標準構成では、ダミーデータ生成ライブラリである fakerphp/fakercomposer.jsonrequire-dev(開発環境用)に記載されています。

本番デプロイ時に composer install --no-dev を実行している環境で、Factoryを呼び出すSeederを動かすと、「Class ‘Faker\Factory’ not found」エラーでSeederが停止します。本番環境で実行するSeederにはFactoryを含めず、固定値や環境変数を使った安全なコードにしましょう。

2. 冪等性(Idempotency)を徹底する

デプロイパイプラインで php artisan db:seed を自動実行する場合、Seederは何度実行されても既存データに悪影響を与えない設計になっている必要があります。前述の updateOrCreateupsert を活用し、主キーやユニークキーの重複エラーが起きないようにしてください。

3. 実行前のDBバックアップ

本番環境でSeederを流す前には、万が一の誤動作や上書きに備えて必ずデータベースのスナップショットやダンプ(バックアップ)を取得しておく運用フローを徹底しましょう。

4. 大量データ投入時のバルクインサートとメモリ節約

何千・何万件ものレコードを User::create() で1件ずつループ処理すると、SQL発行回数が膨大になり実行時間が何十分もかかったりメモリ枯渇を起こしたりします。

大量データ投入時は、次のように insert によるバルクインサート(一括挿入)や chunk を活用し、トランザクションで囲むと高速かつ安全です。

<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;

class LargeDataSeeder extends Seeder
{
    public function run(): void
    {
        $data = [];
        $now = now();

        for ($i = 1; $i <= 5000; $i++) {
            $data[] = [
                'code' => sprintf('ITEM-%05d', $i),
                'name' => "商品名 {$i}",
                'created_at' => $now,
                'updated_at' => $now,
            ];

            // 1,000件ごとに分割してバルクインサート
            if (count($data) >= 1000) {
                DB::table('items')->insert($data);
                $data = [];
            }
        }

        if (!empty($data)) {
            DB::table('items')->insert($data);
        }
    }
}

Seederでよくあるエラーと解決手順(トラブルシューティング)

Seederの作成・実行時によく遭遇するエラーとその解決方法をまとめました。

1. Class “Database\Seeders\XxxSeeder” not found

新規作成したSeederや手動でリネーム・移動したSeederが認識されない場合のエラーです。Composerのオートロードマップが古いことが原因です。

composer dump-autoload

上記コマンドを実行してオートロードキャッシュを再生成してください。

2. db:seedを実行したのにデータが入らない

php artisan db:seed を実行したにもかかわらずテーブルにデータが追加されない場合、DatabaseSeeder.phprun() メソッド内でそのSeederクラスが $this->call() されていない可能性が最も高いです。

単体テストしたい場合は php artisan db:seed --class=Seeder名 を実行するか、DatabaseSeeder.php の配列にクラス名を追加してください。

3. Cannot add or update a child row: a foreign key constraint fails

外部キー制約エラーです。親テーブルのレコードが存在しない状態で子テーブルのデータを挿入しようとすると発生します。

  • 解決策1DatabaseSeeder での実行順序を見直し、親テーブルのSeederを先に実行する
  • 解決策2:テストデータ生成用であれば、一時的に外部キー制約を無効化する(例:Schema::disableForeignKeyConstraints() / Schema::enableForeignKeyConstraints()

4. Integrity constraint violation: 1062 Duplicate entry

主キー(id)や unique 制約が設定されたカラム(emailやコードなど)で値が重複している場合に発生します。

  • Seeder内で updateOrCreatefirstOrCreate を使用する
  • 開発環境であれば事前に php artisan migrate:fresh --seed でテーブルを初期化する

5. Add [xxx] to fillable property to allow mass assignment

Eloquentモデルの Model::create([...]) を使用した際に、モデルクラス側の $fillable プロパティにカラム名が指定されていないことが原因です。モデルに protected $fillable = ['xxx', ...]; を定義するか、Seeder内では DB::table('...')->insert(...) を利用してください。

よくある質問(FAQ)

SeederとFactoryはどう使い分けるべき?

「マスタデータ(固定値)」はSeederに直接定義し、「テスト用ダミーデータ(大量生成)」はFactoryで雛形を作りSeederから呼び出すのが王道の使い分けです。ユニットテストやフィーチャーテスト内でもFactoryを直接 User::factory()->create() のように再利用できます。

Seederの実行結果をロールバック(元に戻す)はできる?

マイグレーションのような「Seeder専用のロールバックコマンド」は標準では用意されていません。開発環境であれば php artisan migrate:fresh --seed で作り直すのが最も手軽です。本番環境でロールバックが必要な場合は、事前にDBバックアップを取得しておくか、データを削除する専用のコマンド・スクリプトを用意します。

まとめ

LaravelのSeederは、初期マスタデータの登録から開発環境のダミーデータ作成まで、データベース操作の自動化に欠かせない重要機能です。

  • 作成php artisan make:seeder Seeder名
  • 実行php artisan db:seed(全実行)または php artisan db:seed --class=Seeder名(単体実行)
  • テストデータ:Factoryと連携して Model::factory()->count(10)->create() で効率的に生成
  • マスタデータupdateOrCreate を活用して何度実行しても安全な冪等性を確保
  • 本番運用DatabaseSeederapp()->isLocal() による環境分岐を行い、Fakerの混入や誤投入を防ぐ

大量のシードデータを一括投入する際のトランザクション活用や、在庫引き当て・決済処理などの同時実行テストに必要な排他ロックの実装については、Laravel lockForUpdate()の使い方|排他ロック(悲観的ロック)とトランザクションの実装・注意点 および Laravelトランザクションの基礎と効果的な活用方法を徹底解説 もあわせてご覧ください。

まずは特定のSeederを --class オプションで単体実行するところから試し、慣れてきたらFactory連携や環境ごとの切り分けを取り入れて、チーム開発の効率を高めていきましょう。

レン (Wren)

こんにちは。レンです。

Laravelのコードの森に住んでいる、小さな案内役です。
ルーティングの枝やクラスの影を歩きながら、コードの流れや仕組みを眺めています。

このサイトでは、Laravelの基本から実装のコツまで、開発で役立つポイントを静かに整理しています。
難しいことを増やすのではなく、コードの見通しが少し良くなるヒントを届けるのが役目です。

「この処理はどこに書くのがいいのか」
「Laravelではどう考えると整理できるのか」

そんな疑問に、小さなメモを残すような気持ちで記事を書いています。

コードを書いている途中で迷ったとき、
このサイトが少し立ち止まって整理できる場所になればうれしいです。

レン (Wren)をフォローする

コメント