浜松のWEBシステム開発・スマートフォンアプリ開発・RTK-GNSS関連の開発はお任せください
株式会社シーポイントラボ
TEL:053-543-9889
営業時間:9:00~18:00(月〜金)
住所:静岡県浜松市中区富塚町1933-1 佐鳴湖パークタウンサウス2F

【Laravel】LaravelらしいFakerのテストデータの増やし方

 Fakerはランダムデータを生成するためのライブラリです。
fzaninotto/Faker: Faker is a PHP library that generates fake data for you
ダミーデータ作成ライブラリFakerの紹介 – 株式会社シーポイントラボ | 浜松のシステム・RTK-GNSS開発
 LaravelではFakerを使って次の様にテストデータの生成機能を決定、よくSeederやTestで用います。

<?php

use App\Models\Eloquents\User;
use Faker\Generator as Faker;
use Illuminate\Database\Eloquent\Factory;

/* @var $factory Factory */

$factory->define(
    User::class,
    static function (Faker $faker) {
        return [
            'name'           => $faker->name,
            'email'          => $faker->unique()->safeEmail,
            'password'       => \Illuminate\Support\Facades\Hash::make('hoge'),
            'remember_token' => $faker->sha1,
            'created_at'     => $faker->dateTimeBetween('-5 years'),
            'updated_at'     => $faker->dateTimeBetween('-5 years'),
        ];
    }
);
factory(User::class, 1000)->create()

 Fakerは多彩な表現ができますが、実務で用いたいデータ全てをカバーできるわけではありません。どうしても解決すべき課題の領域特有の部分はあります。そういった時はFakerを拡張することで対応できます。FakerはProviderというネームスペース以下にランダムデータの定義を持っています。これを拡張します。例は市区町村以下の地名をランダムで生成する拡張です。

<?php

namespace App\Faker\Providers;

class Address extends \Faker\Provider\ja_JP\Address
{
    /**
     * @var array 市区町村以下の地名
     */
    protected static $addressDetailFormats = [
        '{{city}}{{ward}}{{streetAddress}}',
        '{{city}}{{ward}}{{streetAddress}} {{secondaryAddress}}',
    ];

    /**
     * 市区町村以下の地名
     * @return string
     */
    public function addressDetail(): string
    {
        $format = static::randomElement(static::$addressDetailFormats);

        return $this->generator->parse($format);
    }
}

 Providerの適用方法はFaker公式では次の様に紹介されています。
 fzaninotto/Faker: Faker is a PHP library that generates fake data for you#faker-internals-understanding-providers

<?php
$faker = new Faker\Generator();
$faker->addProvider(new Faker\Provider\en_US\Person($faker));
$faker->addProvider(new Faker\Provider\en_US\Address($faker));
$faker->addProvider(new Faker\Provider\en_US\PhoneNumber($faker));
$faker->addProvider(new Faker\Provider\en_US\Company($faker));
$faker->addProvider(new Faker\Provider\Lorem($faker));
$faker->addProvider(new Faker\Provider\Internet($faker));

 使う前のFaker\GeneratorインスタンスにaddProviderします。このやり方は簡単に書けるやり方ですが、Fakerをインスタンス化するたびにaddProviderする必要がありいささか手間がかかります。Laravelではシングルトン(いつどこでインスタンス化しても唯一つの同一のオブジェクトを指すことになるデザインパターン)で作られた仕組みを使って次の様に記述できます。こうすると各プロバイダーに対するaddProviderを一つずる書くだけで済みます。

<?php

namespace App\Providers;

use App\Faker\Providers\Address;
use Faker\Factory;
use Faker\Generator as Faker;
use Illuminate\Support\ServiceProvider;

class FakerServiceProvider extends ServiceProvider
{
    /**
     * @throws \Illuminate\Contracts\Container\BindingResolutionException
     */
    public function register()
    {
        // Laravel本体にFakerが登録され、Laravelの仕組みでFakerをDI(依存性注入)、app()->makeした際はこれでインスタンス化された唯一つのFakerが呼ばれる
        $this->app->singleton(Faker::class, function () {
            // Laravelの設定が空なら日本語ロケールのFakerプロバイダーをベースに使うことを定義
            $fakerLocale = app()->get('config')->get('app.faker_locale', 'ja_JP');
            // Fakerインスタンス化
            $faker = Factory::create($fakerLocale);
            // Fakerにプロバイダーを追加
            $faker->addProvider(new Address($faker));
            // 完成品のFakerを返す
            return $faker;
        });
    }
}
  • この記事いいね! (0)