【Laravel】テストデータ作成【seeder factory faker】


# Fakerとは
Laravelに標準で備わっているライブラリ。
サンプルテストデータ（ダミーデータ）を自動生成してくれます。
例えば、ユーザーを100人登録したいなーとなった時や、異なる内容のテスト記事を1000件作りたいなーとなった時、Fakerを使えば簡単に作成する事ができます。

# Fakerの使い方

## Fakerを日本語化する

おそらく大半の方は日本語のテストデータを使いたいと思うので、日本語化するところから。
`config/app.php`の中に`Faker Locale`という設定項目があるので以下のように変更します。

```config/app.php
    /*
    |--------------------------------------------------------------------------
    | Faker Locale
    |--------------------------------------------------------------------------
    |
    | This locale will be used by the Faker PHP library when generating fake
    | data for your database seeds. For example, this will be used to get
    | localized telephone numbers, street address information and more.
    |
    */

    // 'faker_locale' => 'en_US', //変更前
    'faker_locale' => 'ja_JP', //変更後
```

## `User`と`Article`のテーブル定義

今回は例として、

 - ユーザー：100人
 - 記事：1000件

のテストデータを作成する事にします。
各`Model`と`migration`を用意し、内容を以下のように仮定します。（Modelは割愛）

### User

```crate_user_table.php

class CreateUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->unsignedBigInteger('section_id')->comment('部署ID');
            $table->string('login_id', 100)->comment('ログインID(メールアドレス)');
            $table->string('password', 255)->comment('ログインパスワード');
            $table->string('name', 100)->nullable()->comment('氏名');
            $table->timestamp('logined_at')->nullable()->comment('ログイン日');
            $table->bigInteger('create_user_id')->nullable()->comment('作成者');
            $table->timestamp('created_at')->comment('作成日');
            $table->bigInteger('update_user_id')->nullable()->comment('更新者');
            $table->timestamp('updated_at')->comment('更新日');
            $table->bigInteger('delete_user_id')->nullable()->comment('削除者');
            $table->timestamp('deleted_at')->nullable()->comment('削除日');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('users');
    }
}
```

### Article

```crate_article_table.php

class CreateArticlesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('articles', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->integer('section_id')->comment('部署ID');
            $table->string('title')->comment('タイトル');
            $table->longText('body')->comment('本文');
            $table->bigInteger('create_user_id')->nullable()->comment('作成者');
            $table->timestamp('created_at')->comment('作成日');
            $table->bigInteger('update_user_id')->nullable()->comment('更新者');
            $table->timestamp('updated_at')->comment('更新日');
            $table->bigInteger('delete_user_id')->nullable()->comment('削除者');
            $table->timestamp('deleted_at')->nullable()->comment('削除日');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('articles');
    }
}
```

## SeederファイルとFactoryファイルを作成する

下記コマンドでSeederファイルとFactoryファイルを作成します。

### User

```bash
php artisan make:factory UserFactory
```

### Article

```bash
php artisan make:seeder ArticlesTableSeeder
```
```bash
php artisan make:factory ArticleFactory
```

この時、
Seeder名は複数形
Factory名は単数系
にする点に注意しましょう。

なお、UserのFactoryに関してはLaravelの初期状態から既に存在しているので改めてコマンドを打つ必要はありません。既存のFactoryを編集していきます。


## Factoryを編集

Fakerを使ってFactoryの中身を作成していきます。

### User

```database/factories/UserFactory.php

use Faker\Generator as Faker;
use Illuminate\Support\Facades\Crypt;
use App\User;

$factory->define(User::class, function (Faker $faker) {
    return [
        'section_id' => $faker->randomNumber($nbDigits = 2, $strict = false),
        'login_id' => $faker->word,
        'password' => Crypt::encrypt('abcd1234'), //パスワードを暗号化
        'name' => $faker->name,
        'logined_at' => $faker->dateTime(),
        'create_user_id' => $faker->randomNumber($nbDigits = 2, $strict = false),
        'created_at' => $faker->datetime($max = 'now', $timezone = date_default_timezone_get()),
        'update_user_id' => $faker->randomNumber($nbDigits = 2, $strict = false),
        'updated_at' => $faker->datetime($max = 'now', $timezone = date_default_timezone_get())
    ];
});
```

### Article

```database/factories/ArticleFactory.php

use Faker\Generator as Faker;
use App\Article;

$factory->define(Article::class, function (Faker $faker) {
    return [
        'section_id' => $faker->randomNumber($nbDigits = 2, $strict = false),
        'title' => $faker->sentence(rand(1,4)),
        'body' => $faker->realText(512),
        'create_user_id' => $faker->randomNumber($nbDigits = 2, $strict = false),
        'created_at' => $faker->datetime($max = 'now', $timezone = date_default_timezone_get()),
        'update_user_id' => $faker->randomNumber($nbDigits = 2, $strict = false),
        'updated_at' => $faker->datetime($max = 'now', $timezone = date_default_timezone_get()),
    ];
});
```

Fakerで作成できるデータの種類は豊富に用意されています。
[こちら](https://qiita.com/tosite0345/items/1d47961947a6770053af)の記事を参照してください。

## Seederを編集

続いてSeederファイルを編集していきますが、ここではrunメソッドの中に下記の１行を追加するだけになります。

```php
factory(モデル名::class, 100)->create();
```
これは指定したモデルを使って100件のFactoryで定義したデータを作成するという意味になります。

```database/seeds/ArticlesTableSeeder.php
<?php

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

class ArticlesTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        factory(User::class, 100)->create();
    }
}
```

```database/seeds/ArticlesTableSeeder.php
<?php

use Illuminate\Database\Seeder;
use App\Article;

class ArticlesTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        factory(Article::class, 1000)->create();
    }
}
```

### DatabaseTableSeeder

最後に、忘れずにDatabaseTableSeeder.phpにも記述

```database/seeds/DatabaseTableSeeder.php
<?php

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        if (config('app.env') == 'local') {
            $this->call(UsersTableSeeder::class);
            $this->call(ArticlesTableSeeder::class);
        }
    }
}
```

※テストデータの場合は、このようにifでローカル環境に時のみ呼び出すように指定すると便利です

それではテストデータを生成していきます。

## コマンドでseederを実行する

新しいクラスファイル作成したので

```bash
composer dump-autoload
```
を実行。さらにconfigを触ったので

```bash
php artisan config:cache
```
もしくは

```bash
php artisan config:clear
```

を実行。そして

```bash
php artisan db:seed
```

でseederデータを作成すれば完了です！