本文へ移動
Laravel Tips

ファクトリ(ためしのデータを作る)

テストや最初のデータ入れに使う、ためしのデータを自動で作るファクトリの書き方と、状態・連番・リレーションの作り方を説明します。

ファクトリは、ためしのデータ(名前やメールアドレスなど)を、自動で作るしくみです。アプリのテストをするときや、データベースに最初のデータを入れる(シーディング)とき、1つ1つ値を書くのは大変です。そこで、Eloquent のモデルごとに、「ふつうはこういう値」という既定の値の組を決めておきます。

書き方の例は、新しい Laravel アプリに最初から入っている database/factories/UserFactory.php を見るのが早いです。

php
namespace Database\Factories;

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

/**
 * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\User>
 */
class UserFactory extends Factory
{
    /**
     * The current password being used by the factory.
     */
    protected static ?string $password;

    /**
     * Define the model's default state.
     *
     * @return array<string, mixed>
     */
    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),
        ];
    }

    /**
     * Indicate that the model's email address should be unverified.
     */
    public function unverified(): static
    {
        return $this->state(fn (array $attributes) => [
            'email_verified_at' => null,
        ]);
    }
}

ファクトリは、いちばん簡単な形では、Laravel の基本のファクトリのクラスを受け継いで、definition メソッドを書いたクラスです。definition は、モデルを作るときに入れる「ふつうの値」の組を返します。

ファクトリの中では、fake ヘルパー関数(どこからでも呼べる便利な関数)で、Faker という PHP のライブラリ(便利な部品のまとまり)を使えます。Faker を使うと、テストや最初のデータ入れに使うランダムなデータを、かんたんに作れます。

補足

Faker の言語(ロケール)は、config/app.php の faker_locale で変えられます。

ファクトリを書く#

ファクトリを作る#

ファクトリを作るには、make:factory という Artisan コマンド(php artisan で動かす Laravel のコマンド)を使います。

bash
php artisan make:factory PostFactory

新しいファクトリのクラスは、database/factories に置かれます。

モデルとファクトリの結びつけ#

ファクトリを書いたら、モデルから User::factory() のように呼ぶと、そのモデルのファクトリが手に入ります。この factory メソッドは、モデルに付けた Illuminate\Database\Eloquent\Factories\HasFactory トレイト(クラスに機能を足す部品)が用意する、静的なメソッド(クラス名から直接呼べるメソッド)です。

factory は、名前の決まりから、そのモデルに合うファクトリを探します。探すのは、Database\Factories の名前空間(クラスの置き場所の名前)にある、「モデルの名前 + Factory」という名前のクラスです。この決まりに合わないときは、モデルに UseFactory 属性(PHP の属性。クラスの前に書く印)を付けて、使うファクトリを自分で決めます。

php
use Illuminate\Database\Eloquent\Attributes\UseFactory;
use Database\Factories\Administration\FlightFactory;

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

別のやり方として、モデルの newFactory メソッドを上書きして、使うファクトリをそこから直接返すこともできます。

php
use Database\Factories\Administration\FlightFactory;

/**
 * Create a new factory instance for the model.
 */
protected static function newFactory()
{
    return FlightFactory::new();
}

そのうえで、ファクトリの側に UseModel 属性を付けて、モデルを決めます。

php
use App\Administration\Flight;
use Illuminate\Database\Eloquent\Factories\Attributes\UseModel;
use Illuminate\Database\Eloquent\Factories\Factory;

#[UseModel(Flight::class)]
class FlightFactory extends Factory
{
    // ...
}

状態(ステート)#

状態(ステート)は、ファクトリの「ふつうの値」を少しだけ変えた版です。いくつも用意しておけば、好きなように組み合わせて使えます。たとえば、Database\Factories\UserFactory に、suspended(利用停止)という状態を書いておけます。値の1つだけを「停止中」に変えたものです。

状態のメソッドの中では、ふつう、基本のファクトリが持つ state メソッドを呼びます。state には、クロージャ(名前のない関数)を渡します。クロージャは、ファクトリの元の属性の配列を受け取り、変えたい属性だけを配列で返します。

php
use Illuminate\Database\Eloquent\Factories\Factory;

/**
 * Indicate that the user is suspended.
 */
public function suspended(): Factory
{
    return $this->state(function (array $attributes) {
        return [
            'account_status' => 'suspended',
        ];
    });
}

「trashed」の状態#

Eloquent のモデルが、ソフトデリート(消さずに印を付ける消し方)できるなら、trashed という、最初から用意された状態のメソッドを呼べます。作ったモデルは、すでに「ソフトデリート」された状態になります。trashed は、どのファクトリでも自動で使えるので、自分で書く必要はありません。

php
use App\Models\User;

$user = User::factory()->trashed()->create();

ファクトリのコールバック#

コールバック(あとで呼んでもらう処理)を登録すると、モデルを作った(make)あとや、保存した(create)あとに、ほかの処理を足せます。登録には afterMaking と afterCreating を使います。登録する場所は、ファクトリのクラスに書く configure メソッドの中です。configure は、ファクトリが作られるときに Laravel が自動で呼びます。

php
namespace Database\Factories;

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

class UserFactory extends Factory
{
    /**
     * Configure the model factory.
     */
    public function configure(): static
    {
        return $this->afterMaking(function (User $user) {
            // ...
        })->afterCreating(function (User $user) {
            // ...
        });
    }

    // ...
}

状態のメソッドの中でもコールバックを登録できます。その状態だけの、ほかの処理をしたいときに使います。

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

/**
 * Indicate that the user is suspended.
 */
public function suspended(): Factory
{
    return $this->state(function (array $attributes) {
        return [
            'account_status' => 'suspended',
        ];
    })->afterMaking(function (User $user) {
        // ...
    })->afterCreating(function (User $user) {
        // ...
    });
}
メソッド 働き
definition 属性の既定の値の組を返す
state 属性の一部を変える
configure ファクトリを作るときに、コールバックを登録する場所
afterMaking モデルを作った(保存はしない)あとの処理を決める
afterCreating モデルを保存したあとの処理を決める

ファクトリでモデルを作る#

モデルを作る(保存しない)#

ファクトリを書いたら、モデルの factory メソッド(HasFactory トレイトが用意するもの)でファクトリを取り出し、モデルを作れます。いくつか例を見てみましょう。まずは make で、データベースに保存せずにモデルを作ります。

php
use App\Models\User;

$user = User::factory()->make();

count を使うと、たくさんのモデルのコレクションを作れます。

php
$users = User::factory()->count(3)->make();

状態を当てはめる#

作るモデルに、状態も当てはめられます。いくつもの状態を当てはめたいときは、状態のメソッドを、そのまま続けて呼びます。

php
$users = User::factory()->count(5)->suspended()->make();

属性を上書きする#

モデルの既定の値の一部を変えたいときは、make に値の配列を渡します。決めた属性だけが置き換えられ、ほかは、ファクトリの既定の値のままです。

php
$user = User::factory()->make([
    'name' => 'Abigail Otwell',
]);

別のやり方として、ファクトリに state を直接呼んで、その場で状態を変えることもできます。

php
$user = User::factory()->state([
    'name' => 'Abigail Otwell',
])->make();

補足

ファクトリでモデルを作るときは、マスアサインメント(一括代入)の保護が、自動で止まります。

モデルを保存する#

create は、モデルを作って、Eloquent の save で、データベースに保存します。

php
use App\Models\User;

// Create a single App\Models\User instance...
$user = User::factory()->create();

// Create three App\Models\User instances...
$users = User::factory()->count(3)->create();

create に属性の配列を渡すと、ファクトリの既定の値を上書きできます。

php
$user = User::factory()->create([
    'name' => 'Abigail',
]);

シーケンス#

作るモデルごとに、ある属性の値を、順番に入れ替えたいことがあります。状態の変更を「シーケンス」として書けます。たとえば、作るユーザーごとに、admin カラムの値を Y と N で交互にします。

php
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Sequence;

$users = User::factory()
    ->count(10)
    ->state(new Sequence(
        ['admin' => 'Y'],
        ['admin' => 'N'],
    ))
    ->create();

この例では、admin が Y のユーザーが5人、N のユーザーが5人できます。

必要なら、シーケンスの値にクロージャも使えます。シーケンスが新しい値を必要とするたびに、クロージャが呼ばれます。

php
use Illuminate\Database\Eloquent\Factories\Sequence;

$users = User::factory()
    ->count(10)
    ->state(new Sequence(
        fn (Sequence $sequence) => ['role' => UserRoles::all()->random()],
    ))
    ->create();

シーケンスのクロージャの中では、渡されるシーケンスの $index プロパティ(クラスの中の変数)が使えます。$index は、シーケンスをここまで何回くり返したかの数です。

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

便利な書き方として、sequence でもシーケンスを当てはめられます。中で state を呼んでいるだけです。クロージャか、順番に使う属性の配列を渡します。

php
$users = User::factory()
    ->count(2)
    ->sequence(
        ['name' => 'First User'],
        ['name' => 'Second User'],
    )
    ->create();
メソッド 働き
make モデルを作る(保存しない)
create モデルを作って、保存する
count 作る数を決める
state 属性を変える
sequence 属性を順番に入れ替える(state と Sequence の便利な書き方)

ファクトリでリレーションを作る#

「1対多」のリレーション#

ここからは、ファクトリで、つながったモデルどうし(リレーション。表どうしのつながり)をまとめて作る方法を見ます。アプリに App\Models\User と App\Models\Post があるとします。User には、Post との hasMany(1人が複数の投稿を持つ)のリレーションがあります。このとき、ファクトリの has メソッドに投稿のファクトリを渡すと、投稿を3つ持つユーザーを作れます。

php
use App\Models\Post;
use App\Models\User;

$user = User::factory()
    ->has(Post::factory()->count(3))
    ->create();

has に Post を渡すと、Laravel は名前の決まりから、「User の posts メソッドがこのリレーションだ」と考えます。必要なら、2つ目の引数でリレーションの名前をはっきり書けます。

php
$user = User::factory()
    ->has(Post::factory()->count(3), 'posts')
    ->create();

作る投稿に、状態を当てはめることもできます。状態を決めるのに親のモデル(ここではユーザー)を見たいときは、クロージャを渡します。クロージャは、2つ目の引数で親のモデルを受け取ります。

php
$user = User::factory()
    ->has(
        Post::factory()
            ->count(3)
            ->state(function (array $attributes, User $user) {
                return ['user_type' => $user->type];
            })
    )
    ->create();

マジックメソッドを使う#

リレーションを作るときは、Laravel の「マジックメソッド」(名前から自動で動くメソッド)も使えて便利です。たとえば次の hasPosts は、名前から「User の posts リレーションで投稿を作る」と判断されます。

php
$user = User::factory()
    ->hasPosts(3)
    ->create();

マジックメソッドでリレーションを作るとき、関連するモデルで上書きしたい属性の配列も渡せます。

php
$user = User::factory()
    ->hasPosts(3, [
        'published' => false,
    ])
    ->create();

属性の配列をいくつも渡すと、作るモデルごとに別の値を付けられます。Laravel は、配列を1つずつ順に当てはめます。

php
$user = User::factory()
    ->hasPosts(
        ['title' => 'First Post'],
        ['title' => 'Second Post'],
        ['title' => 'Third Post'],
    )
    ->create();

状態を決めるのに親のモデルを見たいときは、クロージャも渡せます。

php
$user = User::factory()
    ->hasPosts(3, function (array $attributes, User $user) {
        return ['user_type' => $user->type];
    })
    ->create();

「多対1」のリレーション#

「1対多」のリレーションの作り方を見たので、次は、その反対を見ます。for を使うと、ファクトリで作るモデルが属する、親のモデルを決められます。たとえば、1人のユーザーに属する、3つの App\Models\Post を作れます。

php
use App\Models\Post;
use App\Models\User;

$posts = Post::factory()
    ->count(3)
    ->for(User::factory()->state([
        'name' => 'Jessica Archer',
    ]))
    ->create();

作るモデルに結びつけたい親のモデルがすでにあるときは、そのモデルを for に渡せます。

php
$user = User::factory()->create();

$posts = Post::factory()
    ->count(3)
    ->for($user)
    ->create();

マジックメソッドを使う#

「多対1」のリレーションも、マジックメソッドで作れます。たとえば次の例は、名前から「3つの投稿は、Post の user リレーションで1人のユーザーに属する」と判断されます。

php
$posts = Post::factory()
    ->count(3)
    ->forUser([
        'name' => 'Jessica Archer',
    ])
    ->create();

「多対多」のリレーション#

「1対多」のリレーションと同じように、「多対多」のリレーションも、has で作れます。

php
use App\Models\Role;
use App\Models\User;

$user = User::factory()
    ->has(Role::factory()->count(3))
    ->create();

中間表の属性#

モデルをつなぐ、中間表(pivot)に入れる属性を決めたいときは、hasAttached を使います。2つ目の引数に、中間表の属性の名前と値の配列を渡します。

php
use App\Models\Role;
use App\Models\User;

$user = User::factory()
    ->hasAttached(
        Role::factory()->count(3),
        ['active' => true]
    )
    ->create();

状態を決めるのに関連するモデルを見たいときは、クロージャも渡せます。

php
$user = User::factory()
    ->hasAttached(
        Role::factory()
            ->count(3)
            ->state(function (array $attributes, User $user) {
                return ['name' => $user->name.' Role'];
            }),
        ['active' => true]
    )
    ->create();

中間表の配列の配列を渡すと、関連するモデルごとに、別々の中間表のデータを入れられます。

php
$user = User::factory()
    ->hasAttached(
        Role::factory(),
        [
            ['active' => true],
            ['active' => false],
        ]
    )
    ->create();

作るモデルにつなぎたい、すでにあるモデルがあるときは、そのモデルを hasAttached に渡せます。次の例では、同じ3つの役割(ロール)が、3人のユーザー全員につながります。

php
$roles = Role::factory()->count(3)->create();

$users = User::factory()
    ->count(3)
    ->hasAttached($roles, ['active' => true])
    ->create();

マジックメソッドを使う#

「多対多」のリレーションも、マジックメソッドで作れます。たとえば次の例は、名前から「User の roles リレーションで役割を作る」と判断されます。

php
$user = User::factory()
    ->hasRoles(1, [
        'name' => 'Editor'
    ])
    ->create();

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

ポリモーフィックなリレーション(1つの表が、いろいろな表につながるしくみ。くわしくはリレーションのページ)も、ファクトリで作れます。ポリモーフィックな「morph many」は、ふつうの「has many」と同じように作ります。たとえば、App\Models\Post が、App\Models\Comment と morphMany のリレーションを持つときです。

php
use App\Models\Post;

$post = Post::factory()->hasComments(3)->create();

「morph to」のリレーション#

morphTo のリレーションは、マジックメソッドでは作れません。代わりに、for を直接使い、リレーションの名前をはっきり書く必要があります。たとえば、Comment に、morphTo のリレーションを書いた commentable メソッドがあるとします。このとき、for を直接使って、1つの投稿に属する3つのコメントを作れます。

php
$comments = Comment::factory()->count(3)->for(
    Post::factory(), 'commentable'
)->create();

ポリモーフィックな「多対多」のリレーション#

ポリモーフィックな「多対多」(morphToMany / morphedByMany)のリレーションも、ポリモーフィックでない「多対多」と同じように作れます。

php
use App\Models\Tag;
use App\Models\Video;

$video = Video::factory()
    ->hasAttached(
        Tag::factory()->count(3),
        ['public' => true]
    )
    ->create();

マジックメソッドの has 系も、ポリモーフィックな「多対多」に使えます。

php
$video = Video::factory()
    ->hasTags(3, ['public' => true])
    ->create();
メソッド 働き
has 「1対多」「多対多」で、関連するモデルを作る
has + モデルの名前(hasPosts など) 決まりでリレーションを選ぶ、短い書き方
for 属する親のモデルを決める(「多対1」や morphTo)
for + モデルの名前(forUser など) 決まりで親を選ぶ、短い書き方(morphTo には使えない)
hasAttached 中間表の属性を付けて、「多対多」でつなぐ

ファクトリの中でリレーションを決める#

モデルのファクトリの中でリレーションを決めるときは、ふつう、リレーションの外部キーに、新しいファクトリを入れます。多くは、belongsTo や morphTo のような「逆向き」のリレーションで使います。たとえば、投稿を作るときに、新しいユーザーも作りたいなら、次のようにします。

php
use App\Models\User;

/**
 * Define the model's default state.
 *
 * @return array<string, mixed>
 */
public function definition(): array
{
    return [
        'user_id' => User::factory(),
        'title' => fake()->title(),
        'content' => fake()->paragraph(),
    ];
}

リレーションのカラムの値を、同じファクトリのほかの属性から決めたいときは、その属性にクロージャを入れます。クロージャは、ほかの属性の値が決まったあとの配列を受け取ります。

php
/**
 * Define the model's default state.
 *
 * @return array<string, mixed>
 */
public function definition(): array
{
    return [
        'user_id' => User::factory(),
        'user_type' => function (array $attributes) {
            return User::find($attributes['user_id'])->type;
        },
        'title' => fake()->title(),
        'content' => fake()->paragraph(),
    ];
}

すでにあるモデルを使い回す(recycle)#

いくつかのモデルが、同じ相手のモデルとつながっていることがあります。recycle にその相手のモデルを渡すと、ファクトリが作るどのリレーションでも、渡した1つを使い回します。

たとえば、Airline(航空会社)、Flight(便)、Ticket(チケット)のモデルがあり、チケットは航空会社と便に属し、便も航空会社に属すとします。チケットを作るとき、チケットと便で、同じ航空会社を使いたいはずです。そこで、航空会社を recycle に渡します。

php
Ticket::factory()
    ->recycle(Airline::factory()->create())
    ->create();

recycle は、共通のユーザーやチームに属するモデルがあるときに、とくに便利です。

recycle には、すでにあるモデルのコレクションも渡せます。コレクションを渡すと、ファクトリがその種類のモデルを必要とするたびに、コレクションからランダムに1つが選ばれます。

php
Ticket::factory()
    ->recycle($airlines)
    ->create();

関連するページ#

公式ドキュメント(英語)

2026年10月5日時点の内容をもとに、日本語でまとめています。

ページの一覧