メインコンテンツへスキップ

Documentation Index

Fetch the complete documentation index at: https://kawax.biz/llms.txt

Use this file to discover all available pages before exploring further.

ファクトリとは

テストやデータベースシーディングでは、データベースにレコードを挿入する必要があります。 手動で各カラムの値を指定する代わりに、Laravelのモデルファクトリを使うと各Eloquentモデルのデフォルト属性セットを定義できます。 すべての新しいLaravelアプリケーションには database/factories/UserFactory.php が付属しています。
namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;

class UserFactory extends Factory
{
    // 同じパスワードを毎回再ハッシュしないためにキャッシュする
    protected static ?string $password;

    public function definition(): array
    {
        return [
            'name' => fake()->name(),
            'email' => fake()->unique()->safeEmail(),
            'email_verified_at' => now(),
            'password' => static::$password ??= Hash::make('password'),
            'remember_token' => Str::random(10),
        ];
    }
}
fake() ヘルパーを通じて Faker ライブラリが利用でき、様々なランダムデータを生成できます。
Fakerのロケールは config/app.phpfaker_locale オプションで変更できます。

ファクトリの生成

make:factory Artisanコマンドでファクトリを作成します。
php artisan make:factory PostFactory
新しいファクトリクラスは database/factories ディレクトリに配置されます。

モデルとファクトリの自動検出

モデルに HasFactory トレイトを使用すると、Laravelが自動的に対応するファクトリを見つけます。 Database\Factories 名前空間で、モデル名に Factory を付けたクラス名を検索します。 命名規則が合わない場合は UseFactory 属性で明示的に指定できます。
use Illuminate\Database\Eloquent\Attributes\UseFactory;
use Database\Factories\Administration\FlightFactory;

#[UseFactory(FlightFactory::class)]
class Flight extends Model
{
    // ...
}

ファクトリの定義

definition() メソッド

ファクトリの中心となる definition() メソッドでデフォルト属性を定義します。
namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;

class PostFactory extends Factory
{
    public function definition(): array
    {
        return [
            'user_id' => \App\Models\User::factory(),
            'title' => fake()->sentence(),
            'content' => fake()->paragraphs(3, true),
            'published_at' => fake()->optional()->dateTimeBetween('-1 year', 'now'),
        ];
    }
}
Fakerがよく使われるメソッドの一覧:
メソッド生成されるデータ例
fake()->name()John Doe
fake()->email()[email protected]
fake()->sentence()ランダムな文
fake()->paragraph()ランダムな段落
fake()->numberBetween(1, 100)1100の整数
fake()->dateTime()ランダムな日時
fake()->boolean()true / false

ファクトリステート (States)

ステートメソッドを使うと、ファクトリに対して個別の変更を定義できます。
use Illuminate\Database\Eloquent\Factories\Factory;

class UserFactory extends Factory
{
    public function definition(): array
    {
        return [
            'name' => fake()->name(),
            'email' => fake()->unique()->safeEmail(),
            'account_status' => 'active',
        ];
    }

    // 停止中ユーザーのステート
    public function suspended(): static
    {
        return $this->state(fn (array $attributes) => [
            'account_status' => 'suspended',
        ]);
    }

    // 管理者ユーザーのステート
    public function admin(): static
    {
        return $this->state(fn (array $attributes) => [
            'is_admin' => true,
        ]);
    }
}
ステートは組み合わせて使えます。
$user = User::factory()->suspended()->create();
$admin = User::factory()->admin()->create();

ソフトデリートのステート

ソフトデリート対応のモデルには、ビルトインの trashed() ステートが利用できます。
$user = User::factory()->trashed()->create();

ファクトリコールバック (Callbacks)

afterMakingafterCreating でモデル生成後の追加処理を定義します。
namespace Database\Factories;

use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;

class UserFactory extends Factory
{
    public function configure(): static
    {
        return $this->afterMaking(function (User $user) {
            // make() 後に実行(DBには保存されていない)
        })->afterCreating(function (User $user) {
            // create() 後に実行(DBに保存済み)
        });
    }

    // ...
}
ステートメソッド内でもコールバックを登録できます。
public function withProfile(): static
{
    return $this->state(fn (array $attributes) => [])
        ->afterCreating(function (User $user) {
            $user->profile()->create([
                'bio' => fake()->paragraph(),
            ]);
        });
}

モデルの生成

make() — DBに保存しない

use App\Models\User;

// 1件生成
$user = User::factory()->make();

// 3件生成(コレクションで返る)
$users = User::factory()->count(3)->make();

create() — DBに保存する

// 1件生成してDBに保存
$user = User::factory()->create();

// 3件生成してDBに保存
$users = User::factory()->count(3)->create();

属性の上書き

make()create() に配列を渡すと、特定の属性だけ上書きできます。
$user = User::factory()->make([
    'name' => '山田太郎',
]);

$user = User::factory()->create([
    'name' => '鈴木花子',
    'email' => '[email protected]',
]);
ステートを使ったインライン上書きも可能です。
$user = User::factory()->state([
    'name' => '田中一郎',
])->make();
ファクトリでモデルを生成する際、マスアサインメント保護は自動的に無効になります。

Sequence(シーケンス)

複数モデルを生成する際に属性を交互に変える場合は Sequence を使います。
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Sequence;

$users = User::factory()
    ->count(10)
    ->state(new Sequence(
        ['admin' => 'Y'],
        ['admin' => 'N'],
    ))
    ->create();
// 5件はadmin='Y'、5件はadmin='N'で生成される
sequence() メソッドを使うとより簡潔に書けます。
$users = User::factory()
    ->count(2)
    ->sequence(
        ['name' => '最初のユーザー'],
        ['name' => '2番目のユーザー'],
    )
    ->create();
クロージャでランダムな値を動的に生成することもできます。
use Illuminate\Database\Eloquent\Factories\Sequence;

$users = User::factory()
    ->count(10)
    ->state(new Sequence(
        fn (Sequence $sequence) => ['name' => 'ユーザー ' . $sequence->index],
    ))
    ->create();

リレーションシップのファクトリ

Has Many(1対多)

has() メソッドで「1対多」リレーションを持つモデルを生成します。
use App\Models\Post;
use App\Models\User;

// 3件のPostを持つUserを生成
$user = User::factory()
    ->has(Post::factory()->count(3))
    ->create();
マジックメソッドを使うとより簡潔に書けます(has + リレーション名の複数形)。
$user = User::factory()
    ->hasPosts(3)
    ->create();

// 属性を上書き
$user = User::factory()
    ->hasPosts(3, ['published' => false])
    ->create();

Belongs To(逆リレーション)

for() メソッドで「属する」親モデルを指定します。
use App\Models\Post;
use App\Models\User;

// 特定ユーザーに属する3件のPostを生成
$posts = Post::factory()
    ->count(3)
    ->for(User::factory()->state(['name' => '田中花子']))
    ->create();

// 既存モデルを親として使用
$user = User::factory()->create();
$posts = Post::factory()->count(3)->for($user)->create();
マジックメソッド版:
$posts = Post::factory()
    ->count(3)
    ->forUser(['name' => '田中花子'])
    ->create();

Many to Many(多対多)

hasAttached() メソッドで多対多リレーションを扱います。中間テーブルの属性も指定できます。
use App\Models\Role;
use App\Models\User;

$user = User::factory()
    ->hasAttached(
        Role::factory()->count(3),
        ['active' => true]  // 中間テーブルの属性
    )
    ->create();
マジックメソッド版:
$user = User::factory()
    ->hasRoles(1, ['name' => 'Editor'])
    ->create();

ポリモーフィックリレーション

通常の「1対多」と同様に has() またはマジックメソッドが使えます。
use App\Models\Post;

$post = Post::factory()->hasComments(3)->create();
morphTo リレーションにはマジックメソッドは使えません。for() に関係名を明示します。
$comments = Comment::factory()->count(3)->for(
    Post::factory(), 'commentable'
)->create();

ファクトリ内でのリレーション定義

definition() 内で外部キーに別のファクトリを割り当てると、モデル生成時に自動的に親モデルも生成されます。
class PostFactory extends Factory
{
    public function definition(): array
    {
        return [
            'user_id' => \App\Models\User::factory(),
            'title' => fake()->sentence(),
            'content' => fake()->paragraph(),
        ];
    }
}

recycle() — 既存モデルの再利用

複数のリレーションで同じモデルインスタンスを再利用したい場合は recycle() を使います。
// 同じAirlineをTicketとFlightの両方で使い回す
Ticket::factory()
    ->recycle(Airline::factory()->create())
    ->create();

// コレクションからランダムに選択
$airlines = Airline::factory()->count(3)->create();
Ticket::factory()->count(10)->recycle($airlines)->create();

シーディングでの利用

DatabaseSeeder やシーダークラスからファクトリを呼び出します。
namespace Database\Seeders;

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

class DatabaseSeeder extends Seeder
{
    public function run(): void
    {
        // 10件のユーザーを生成し、各ユーザーに3件の投稿を持たせる
        User::factory()
            ->count(10)
            ->hasPosts(3)
            ->create();
    }
}
シーダーの実行:
php artisan db:seed

テストでの利用

テストでは RefreshDatabase トレイトと組み合わせてファクトリを使います。
namespace Tests\Feature;

use App\Models\User;
use App\Models\Post;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class PostTest extends TestCase
{
    use RefreshDatabase;

    public function test_user_can_view_their_posts(): void
    {
        $user = User::factory()->create();
        $posts = Post::factory()->count(3)->for($user)->create();

        $response = $this->actingAs($user)
            ->get('/dashboard');

        $response->assertOk();
        $response->assertSee($posts->first()->title);
    }

    public function test_suspended_user_cannot_post(): void
    {
        $user = User::factory()->suspended()->create();

        $response = $this->actingAs($user)
            ->post('/posts', ['title' => 'テスト']);

        $response->assertForbidden();
    }
}
RefreshDatabase はテストごとにデータベースをリセットするため、テスト間でデータが干渉しません。
PestでテストするときもファクトリのAPIは同じです。 uses(RefreshDatabase::class) を使ってデータベースをリセットしてください。

次のステップ

データベースシーディング

シーダーとファクトリを組み合わせて初期データを投入する方法を確認します。

テスト入門

Laravelのテスト機能とRefreshDatabaseトレイトの使い方を確認します。
Last modified on April 12, 2026