Laravelのマイグレーション、シーダー、ファクトリー、フェイカーってどれが何なの？実際どうやって使うの？

# はじめに
どの機能も何となく使った事はあるし、何となく使い方は分かってるつもりだけど、
ちゃんと役割を理解しているかと言われたら、なーんか曖昧何だよな〜って思っていたので備忘録としてまとめる事にしました。

どんなシチュエーションの時に、どうやって使うのか？を焦点に書きたいと思います。
※後述するユースケースは全てLaravelのプロジェクトという前提です。
※本記事は環境Laravel Framework 9.47.0です。

誰かの一助になれば幸いです。

# それぞれの概要
### マイグレーション（migration）
役割：DBにテーブルとカラムを作成する
必要なもの：マイグレーションファイル
### シーダー（seeder）
役割：DBのテーブルにデータを作成する
必要なもの：シーダーファイル
※Laravelに元からあるdatabase/seeders/DatabaseSeeder.phpに追記は別途必要

### ファクトリー（Factory）
役割：DBのテーブルに簡単に大量にデータを作成する
必要なもの：ファクトリーファイル、モデル
※ファクトリーファイルはシーダーファイルの代わりに作成するイメージ。
Laravelに元からあるdatabase/seeders/DatabaseSeeder.phpに追記は別途必要

### フェイカー（Faker）
役割：DBのテーブルに簡単にそれっぽいダミーデータを作成する
必要なもの：ファクトリーファイル、モデル
※フェイカーは基本的にファクトリーと合わせ技で利用する。
フェイカーを使うのにファイルの作成とかは不要だよ！
※Laravelに元からあるdatabase/seeders/DatabaseSeeder.phpに追記は別途必要


# マイグレーション（migration）
さて、まずはマイグレーションからだ。
どんなプロジェクトでもテーブルが無いことには始まらない。

### ユースケース

DBにテーブルを作成したいけど、phpMyAdminとかでポチポチ何個もテーブル作るのめんどくさい・・・
複数人でやるプロジェクトだと、もしテーブルの構成間違えて作った人がいたらAさんの環境では動くけど、Bさんの環境だと動かないとかなるかもだし怖い・・・
→マイグレーションを利用しよう！

### 手順
マイグレーションファイルを作成する
↓
作成されたマイグレーションファイルを編集してテーブルの構成（カラムなど）を記述する。
↓
マイグレーションファイルを実行する

### 使い方
#### STEP１
マイグレーションファイルを作成する。
〇〇には作成したいマイグレーションファイル名を指定する。
※指定するとは言っても例の「create_samples_table」のようにcreate_テーブル名_tableにするのが通例。
〇〇テーブルを作る為のファイルってのが名前から推測できるね！

```:使い方
php artisan make:migration 〇〇
```
```:例
php artisan make:migration create_samples_table
```

ちなみにモデルを作成する際に-mオプションを付ければモデルのファイルと同時にマイグレーションファイルを生成してくれるよ！

```:使い方
php artisan make:model 〇〇 -m
```
```:例
php artisan make:model Sample -m
```

#### STEP2
作成されたマイグレーションファイルを編集してテーブルの構成（カラムなど）を記述する。

さて、database/migrations配下に日付付きのマイグレーションファイルが生成されていると思うので中身を見てみよう。
```php:2023_02_24_144650_create_samples_table.php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('samples', function (Blueprint $table) {
            $table->id();
            $table->timestamps();
        });
    }

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

```
細かい説明は割愛するが、upメソッドの中でSchemaファサードのcreateメソッドが実行されているよね？
第一引数はテーブル名、上記コードでは'samples'
第二引数はクロージャが使われているね。

このクロージャの中で「$table->〇〇」のように記述する事でテーブルのカラムを作成することが出来るって訳だ！
```php:上記コードの一部抜粋
 Schema::create('samples', function (Blueprint $table) {
            $table->id();
            $table->timestamps();
        });
```
今回は、nameカラムとageカラムを追加しただけのシンプルな編集をするよ！
```php:編集後
 Schema::create('samples', function (Blueprint $table) {
            $table->id();
            $table->timestamps();
            $table->string('name');
            $table->integer('age');
        });
```
ポイントは$tableにアロー演算子で繋げてstringやintegerといった型の名前のメソッドを使ってカラムを作成している事。
また、カラム名は型の名前のメソッドの引数として設定している事だね。

#### STEP３
マイグレーションファイルを実行する。
あとは実行するだけ。

```:使い方
php artisan migrate
```

これで、phpMyAdminのようなGUIツールを使うなりすればちゃんとDBにテーブルが作成されている事が確認できるはずだ！

# シーダー（seeder）
お次は、シーダーだ。
テーブルがあってもデータが無いことには始まらない。

### ユースケース

テーブルを作成したのはいいけど、phpMyAdminとかでポチポチ何個もデータを作るのはめんどくさい・・・
→シーダーを利用しよう！

### 手順
シーダーファイルを作成する。
↓
作成されたシーダーファイルを編集してテーブルに作成したいデータを記述する。
↓
作成されたシーダーファイルをDatabaseSeeder.phpに追記する。
↓
シーダーを実行する。

### 使い方
#### STEP１
シーダーファイルを作成する。
〇〇には作成したいマイグレーションファイル名を指定する。
※指定するとは言っても例の「SampleSeeder」のように頭文字を大文字にしてテーブル名の単数系にするのが通例。
〇〇テーブルのシーダーファイルってのが名前から推測できるね！

```:使い方
php artisan make:seeder 〇〇
```
```:例
php artisan make:seeder SampleSeeder
```
#### STEP2
作成されたシーダーファイルを編集してテーブルに作成したいデータを記述する。

さて、database/seeders配下にシーダーファイルが生成されていると思うので中身を見てみよう。

```php:SampleSeeder.php
<?php

namespace Database\Seeders;

use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;

class SampleSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        //
    }
}

```
細かい説明は割愛するが、runメソッドの中にテーブルに追加したいデータを書いていけば良いって訳だ！
具体的には、DBファサードのtableメソッドで、データを挿入するテーブルを指定。
そのままアロー演算子で繋げてinsertメソッドを実行するんだが、その引数として連想配列でキーにカラム名、値にデータを指定してあげればOKだ！
おっと、生成されたシーダーファイルは初期状態ではDBファサードがuseされていないから追加するのを忘れちゃいけないぜ？

今回は、レコードを3つ作成してみるよ！
```php:SampleSeeder.php
<?php

namespace Database\Seeders;

use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
// 追加※DBファサードをuse
use Illuminate\Support\Facades\DB;

class SampleSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        // 追加※3つのレコードを作成(配列の中に配列があるから気をつけてね！)
        DB::table('samples')->insert(
            [
                [
                    'name' => '田中',
                    'age' => 20,
                ],
                [
                    'name' => '山田',
                    'age' => 30,
                ],
                [
                    'name' => '佐藤',
                    'age' => 40,
                ],
            ]
        );
    }
}

```



#### STEP3
作成されたシーダーファイルをDatabaseSeeder.phpに追記する。
シーダーファイルはこれでバッチリ。
でもね、DatabaseSeeder.phpに追記してあげないと動いてくれないんだ・・・
まずはdatabase/seeders配下のDatabaseSeeder.phpの中身を見てみよう！

```php:DatabaseSeeder.php
<?php

namespace Database\Seeders;

// use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        $this->call([
            JobSeeder::class,
        ]);
    }
}

```

細かい説明は割愛するが、runメソッドの中に追加したいシーダーを書いていけば良いって訳だ！
具体的には、runメソッドの中の$this->callメソッド内に「クラス名::class」と記述してやればOKだ！
おっと、DatabaseSeeder.phpは初期状態では先ほど作成したシーダーファイルがuseされていないから追加するのを忘れちゃいけないぜ？

実際にシーダーを追加したファイルがこれだ！
```php:DatabaseSeeder.php
<?php

namespace Database\Seeders;

// use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
//追加※先ほど作成したSampleSeeder
use Database\Seeders\SampleSeeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        $this->call([
            JobSeeder::class,
            SampleSeeder::class,
        ]);
    }
}

```


#### STEP4
シーダーを実行する。
あとは実行するだけ！
```:使い方
php artisan db:seed
```

ちなみにマイグレーションとシーダーの実行は同時にする事が出来るよ！
下記コマンドではDBのテーブルを全て削除した後に、マイグレーションとシーダーの実行を一気にやってくれる！
（DBを一旦綺麗にしたい時なんかに便利！）
```:使い方
php artisan migrate:fresh --seed
```

これでDBにレコードの追加も出来たね！
ただもっと便利な方法もあるから紹介していくよ！

# ファクトリー（Factory）
いよいよファクトリーの出番だ。
コイツを使えばシーダーファイルを作成するよりも、簡単にデータを大量生産することが出来るぞ。

### ユースケース

シーダーでデータを作成出来るのは確かに便利だけど、大量にレコードを作成するのはやっぱり大変だなぁ・・・
→ファクトリーを利用しよう！

### 手順
モデルを作成する。
↓
ファクトリーファイルを作成する。
↓
作成されたファクトリーファイルを編集してテーブルに作成したいデータを記述する。
↓
作成されたファクトリーファイルをDatabaseSeeder.phpに追記する。
↓
ファクトリーを実行する。

### 使い方
#### STEP１
モデルを作成する。
〇〇には作成したいモデル名を指定する。
※指定するとは言っても例の「Sample」のように頭文字を大文字にしてテーブル名の単数系にするのが通例。
〇〇テーブルのモデルってのが名前から推測できるね！

```:使い方
php artisan make:model 〇〇
```
```:例
php artisan make:model Sample
```

#### STEP2
ファクトリーを作成する。
〇〇には作成したいファクトリーのモデル名を指定する。

```:使い方
php artisan make:factory 〇〇
```
```:例
php artisan make:factory Sample
```

#### STEP3
作成されたファクトリーファイルを編集してテーブルに作成したいデータを記述する。

さて、database/factories配下にファクトリーファイルが生成されていると思うので中身を見てみよう。

```php:SampleFactory.php
<?php

namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;

/**
 * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Sample>
 */
class SampleFactory extends Factory
{
    /**
     * Define the model's default state.
     *
     * @return array<string, mixed>
     */
    public function definition()
    {
        return [
            //
        ];
    }
}
```
細かい説明は割愛するが、definitionメソッドの中のreturnの配列にテーブルに追加したいデータを連想配列で書いていけばOKだ！
書き方はシーダーファイルとほとんど同じだから簡単だろう？

実際にデータを追加したファイルがこれだ！
```php:SampleFactory.php
<?php

namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;

/**
 * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Sample>
 */
class SampleFactory extends Factory
{
    /**
     * Define the model's default state.
     *
     * @return array<string, mixed>
     */
    public function definition()
    {
        //追加※returnで返す配列に記述
        return [
            'name' => '川島',
            'age' => 20,
        ];
    }
}

```
#### STEP4
作成されたファクトリーファイルをDatabaseSeeder.phpに追記する。
ファクトリーファイルはこれでバッチリ。
でもね、シーダーファイルと同じでDatabaseSeeder.phpに追記してあげないと動いてくれないんだ・・・

実際に編集後のDatabaseSeeder.phpがこれだ！

```php:DatabaseSeeder.php
<?php

namespace Database\Seeders;

// use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Database\Seeders\SampleSeeder;
// 追加※Sampleモデルを読み込み
use App\Models\Sample;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        $this->call([
            JobSeeder::class,
            SampleSeeder::class,
        ]);
        // 追加※Sampleモデルのファクトリメソッドを実行。
        Sample::factory()->count(10)->create();
    }
}


```

ポイントは4つ。
・use文でApp\Models\Sampleを読み込んでいること。
・シーダーファイルの時とは違ってモデルのファサードを利用している事。
・シーダーファイルと違って$this->callメソッドの引数としてクラスを渡している訳ではない事。
・モデルのファクトリメソッドを利用している事、そのままアロー演算子で繋げてcountメソッドで作成するデータの数を引数で指定して、さらにアロー演算子で繋げてcreateメソッドを実行。
（モデルとファクトリーが紐づいているので使える）


#### STEP5
シーダーを実行する。
あとは実行するだけ！
```:使い方
php artisan db:seed
```

これでDBに簡単に10個レコードの追加も出来たね！
今回の例のように全く同じレコードを何個も作成しても実用性は低い。
例えばageカラムを複数作成したい時、PHPのrand関数を使ってランダムな整数を作成したり・・・夢が広がるね！

# フェイカー（Faker）
最後はフェイカーの出番だ。
コイツを使えば、簡単にそれっぽいダミーデータを大量生産することが出来るぞ。

### ユースケース

ファクトリーでデータを作成出来るのは確かに便利！
でもageカラムみたいに整数が入るカラムならともかく、名前カラムや住所カラムにそれっぽいダミーデータを大量に簡単に作れればな〜。
→フェイカーを利用しよう！

### 手順
モデルを作成する。
↓
ファクトリーファイルを作成する。
↓
作成されたファクトリーファイルを編集してテーブルに作成したいデータを記述する
（ここでフェイカーを使う！）
↓
作成されたファクトリーファイルをDatabaseSeeder.phpに追記する。
↓
シーダーを実行する。

### 使い方
#### STEP1~5

基本的にはファクトリーを単体で使う時と手順は同じなので、今回は先ほど作成したSampleモデル、Sampleファクトリーファイルをそのまま流用させてくれ！
フェイカーを使うという事は、具体的にはファクトリーファイルの記述の仕方がファクトリー単体で使う時とは異なるという事だ！

実際にフェイカーを利用するパターンの、編集後のファクトリーファイルがこれだ！
```php:SampleFactory.php
<?php

<?php

namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;

/**
 * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Sample>
 */
class SampleFactory extends Factory
{
    /**
     * Define the model's default state.
     *
     * @return array<string, mixed>
     */
    public function definition()
    {
        
        return [
            // 'name' => '川島',
            // 'age' => 20,
            //追加※fakerを利用
            'name' => $this->faker->name,
            'age' => $this->faker->numberBetween(20,80)
        ];
    }
}

```

ポイントはdefinition関数内で実行されるreturnの中の連想配列の書き方が変わる事だ。
フェイカーを使わずにファクトリーを単体で使っていた時は連想配列の値を直接'川島'や２０のように記述していたが、フェイカーを使う時はthis->fakerのように記述をしている。
今回はthis->faker->nameとしてランダムな名前を生成し、this->faker->numberBetween(20,80)として20~80の間のランダムな整数を作成している。

あとは実行するだけ！

```:使い方
php artisan db:seed
```

これでDBに簡単にそれっぽい10個のダミーデータの追加も出来たね！

# まとめ
実際にはファクトリーやシーダーを単体で使うという事はあまり無いかと思いますが、今回はマイグレーション、シーダー、ファクトリー、フェイカーの違いをしっかりと理解する事が目的だったので単体での例を中心に記述いたしました（ファクトリーを除く）

ダミーデータを大量生産したいならファクトリーファイルを、そうで無いならシーダーファイルを作成する。このような認識でひとまず良さそう。
また、実際はファクトリー単体で使わずにフェイカーと組み合わせて使うことがほとんどという事。
シーダーファイルも、ファクトリーファイルも、実行するにはdatabase/seeders配下のDatabaseSeeder.phpに記述が必要という事を押さえておこう。
ファクトリーを実行する時も、あくまでシーダーを実行するって言い回しだから混乱してたのかもな〜なんて思いました。でもDatabaseSeeder.phpはseeders配下にあるって考えたらすんなり受け入れられました。