fakerphp/fakerでテストデータとシーダーを効率化する

概要

開発やテストで「それっぽいダミーデータ」を大量に用意したい場面は多い。手でレコードを打ち込むのは非効率で、本番データをコピーして使うと個人情報の混入事故にもつながる。

fakerphp/faker(https://fakerphp.org/)は、氏名・住所・メール・日付などの擬似データを生成するPHPライブラリ。旧 fzaninotto/faker の後継としてコミュニティがメンテナンスしており、Laravel をはじめ多くの環境で標準的に使われている。

本記事では、インストールから基本的な使い方、シーダー・ファクトリとの組み合わせ、unique() / optional() などの実用的な修飾子、再現性の確保までをハンズオン形式でまとめる。

環境

  • PHP 8.1 以上
  • Composer
  • fakerphp/faker(本記事執筆時点の最新系)
  • Laravel 10 以降(シーダー・ファクトリ例で使用)

発生した問題

ダミーデータ整備でよくある困りごとは次のあたりだ。

  • 手動でテストデータを作っており、量を増やすのが面倒
  • 本番データをコピーして開発環境に流用し、個人情報が混入する
  • テストが実行ごとに違うデータを使い、失敗の再現ができない
  • 日本語環境なのに英語の名前・住所になってしまう

原因

これらは「ダミーデータ生成を仕組み化していない」ことに起因する。生成ロジックを手続き的に書き散らすと、量・ロケール・再現性のコントロールがすべて個別対応になってしまう。Faker を介して生成ルールを一箇所に寄せることで解決できる。

対応方法

インストール

開発・テスト専用なので --dev で入れる。

composer require --dev fakerphp/faker

基本的な使い方

Factory::create() でジェネレータを生成し、プロパティアクセスでデータを得る。

<?php

require 'vendor/autoload.php';

$faker = \Faker\Factory::create();

echo $faker->name;         // "John Doe"
echo $faker->email;        // "jdoe@example.org"
echo $faker->address;      // 住所
echo $faker->text(100);    // ランダムな文章

日本語ロケール

ロケールを ja_JP で生成すると、日本語の氏名・カナ・住所・電話番号が出る。

$faker = \Faker\Factory::create('ja_JP');

echo $faker->name;          // "佐藤 花子"
echo $faker->kanaName;      // "サトウ ハナコ"
echo $faker->company;       // "株式会社〇〇"
echo $faker->prefecture;    // "東京都"
echo $faker->phoneNumber;   // "090-1234-5678"

よく使うフォーマッタ

// 数値
$faker->numberBetween(1, 100);     // 範囲指定
$faker->randomNumber(5);           // 桁数指定
$faker->randomFloat(2, 0, 1000);   // 小数点以下2桁

// 選択
$faker->randomElement(['A', 'B', 'C']);        // 1つ選ぶ
$faker->randomElements(['A', 'B', 'C'], 2);    // 複数選ぶ

// 日付
$faker->dateTimeBetween('-1 year', 'now');     // 期間内のDateTime
$faker->dateTimeThisMonth();

// 真偽・その他
$faker->boolean(70);               // 70%の確率でtrue
$faker->uuid;
$faker->url;

unique() — 重複しない値

メールアドレスのように UNIQUE 制約があるカラムでは unique() を挟む。生成不能になると OverflowException を投げるので母数には注意する。

$faker = \Faker\Factory::create('ja_JP');

$emails = [];
for ($i = 0; $i < 100; $i++) {
    $emails[] = $faker->unique()->safeEmail;
}
// すべて重複なし

optional() — ときどきnull

NULL を許容するカラムのテストに使う。デフォルトは50%の確率で null。

$faker->optional()->text;          // 50%でnull
$faker->optional(0.9)->text;       // 10%でnull(0.9の確率で値)
$faker->optional(default: '未設定')->text; // nullの代わりに既定値

再現性 — seed()

テストで「同じデータが毎回出る」ようにするには seed を固定する。失敗の再現に効く。

$faker = \Faker\Factory::create('ja_JP');
$faker->seed(1234);

echo $faker->name; // seedが同じなら常に同じ結果

実装例

Laravel のファクトリで使う

Laravel ではモデルファクトリ内で fake() ヘルパ(内部的に Faker)を使う。

<?php

namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;

class UserFactory extends Factory
{
    public function definition(): array
    {
        return [
            'name'              => fake()->name(),
            'email'             => fake()->unique()->safeEmail(),
            'email_verified_at' => now(),
            'profile'           => fake()->optional()->realText(100),
            'created_at'        => fake()->dateTimeBetween('-1 year', 'now'),
        ];
    }

    // 状態(state)で属性を上書き
    public function unverified(): static
    {
        return $this->state(fn () => ['email_verified_at' => null]);
    }
}

ロケールを ja_JP に固定したい場合は config/app.php の faker_locale を設定する。

'faker_locale' => 'ja_JP',

シーダーで一括投入

<?php

namespace Database\Seeders;

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

class UserSeeder extends Seeder
{
    public function run(): void
    {
        // 50件作成
        User::factory()->count(50)->create();

        // 未認証ユーザーを10件
        User::factory()->count(10)->unverified()->create();
    }
}
php artisan db:seed --class=UserSeeder

素のPHP/PHPUnitで使う

Laravel でなくても同じ。PHPUnit のテストでジェネレータを用意しておくと、フィクスチャ生成がすっきりする。

<?php

use PHPUnit\Framework\TestCase;

class OrderTest extends TestCase
{
    private \Faker\Generator $faker;

    protected function setUp(): void
    {
        $this->faker = \Faker\Factory::create('ja_JP');
        $this->faker->seed(42); // テストの再現性を担保
    }

    public function test_合計金額の計算(): void
    {
        $price    = $this->faker->numberBetween(100, 10000);
        $quantity = $this->faker->numberBetween(1, 10);

        // ... 検証
    }
}

カスタムプロバイダで独自データ

ドメイン固有の値(例:自社の商品コード形式)が欲しいときはプロバイダを足せる。

<?php

use Faker\Provider\Base;

class ProductCodeProvider extends Base
{
    public function productCode(): string
    {
        // 例: PRD-XXXX 形式
        return 'PRD-' . $this->generator->numerify('####');
    }
}

$faker = \Faker\Factory::create('ja_JP');
$faker->addProvider(new ProductCodeProvider($faker));

echo $faker->productCode(); // "PRD-0472"

確認方法

  • php artisan db:seed 実行後、対象テーブルのレコード件数と内容を確認する
  • unique() を使った箇所で UNIQUE 制約違反が出ないことを確認する
  • seed() を固定したテストを2回実行し、同じ値が得られることを確認する
  • ロケールを ja_JP にして、氏名・住所が日本語になっていることを確認する

注意点

  • 本番環境でシーダーを流さない。テスト・開発用のデータ生成に限定する
  • unique() は母数が尽きると OverflowException を投げる。狭い範囲 × 大量生成を避ける
  • realText() は実在の文章片を組み替えるため、短すぎる長さ指定だと失敗することがある
  • 生成データはあくまで擬似。実在の個人を指す可能性はゼロではないので、公開物にそのまま貼らない
  • Laravel 旧バージョンでは $this->faker、新しめでは fake() ヘルパが推奨。プロジェクトの慣習に合わせる

まとめ

fakerphp/faker を使うと、ダミーデータ生成を「仕組み」に落とし込める。

  • Factory::create('ja_JP') で日本語データ
  • unique() / optional() で制約・NULL を再現
  • seed() でテストの再現性を確保
  • Laravel ではファクトリ+シーダーで一括投入

手作業のテストデータ整備や本番データ流用をやめ、Faker に寄せることで、個人情報混入のリスクも減らせる。まずは composer require --dev fakerphp/faker から試してほしい。

\ 最新情報をチェック /

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください。