Laravelのfactoryを使って、中間テーブルにデータを挿入したりしてみる。

今回はLaravelのfactory機能を使って、ダミーデータを作成したり、中間テーブルにデータを挿入したりします。

ぶっちゃけ、そこまで難しくありません。

ざっくりしたファクトリーを使用する手順は、
1.ファクトリーを作って、テーブルに挿入するデータのルールを記述する。
2.シーダーを作って、実際にデータを挿入する処理を記述する。
3.作ったシーダーをコマンドで実行できるように登録する。
これだけです。



**今回は、`novelsテーブル（小説）`と`tagsテーブル（タグ）`の中間テーブル`novel_tagテーブル`にデータを挿入する設定です。
また、最大で6つまで小説にタグを設定できるという仮定で進めていきます。**

それではガンガンやっていきましょう。

##1.ファクトリーを作って、テーブルに挿入するデータのルールを記述する。
まずは`novelsテーブル（小説）`と`tagsテーブル（タグ）`用のファクトリーを作成します。

下記コマンドを実行してください。

```
php artisan make:factory NovelFactory
php artisan make:factory TagFactory
```

これで、`app > database > factories`直下に`NovelFactory.php`と`TagFactory.php`が作成されているはず。

それぞれに下記の記述を追加します。

```php:NovelFactory.php
<?php

use App\Model;
use Faker\Generator as Faker;

$factory->define(App\Novel::class, function (Faker $faker) {

    //Usersテーブルの中からランダムに1つのレコードのidを取得する。
    $user_id = App\User::all()->random(1)[0]->id;

    return [
        'title'=>$faker->word, 
        'summary'=>$faker->sentence,
        'user_id'=>$user_id,
    ];
});


```

```php:TagFactory.php
<?php

use App\Model;
use Faker\Generator as Faker;

$factory->define(App\Tag::class, function (Faker $faker) {
    return [
        'name'=>$faker->word,
    ];
});


```

簡単に解説しておきます。
まずFactoryを使う時は`$factory->define(App\Novel::class, function (Faker $faker) {ココ});`の中にコードを記述します。

`$user_id = App\User::all()->random(1)[0]->id;`こちらのコードはUsersテーブルからランダムで1つのレコードを取得。そして、そのレコードのidを取得しています。
`randomメソッド`を使えば、引数に与えた数値の数だけ、コレクションの中からインスタンスを取得することができます。
ここで取得した`usersテーブルのid`を`'user_id'=>$user_id,`で外部キーを実現しています。


##2.シーダーを作って、実際にデータを挿入する処理を記述する。
次にシーダーを作成します。

```
php artisan make:seed NovelsTableSeeder
php artisan make:seed TagsTableSeeder
```

これで`app > database > seeds`の中に`NovelsTableSeeder.php`と`TagsTableSeeder.php`ができているはず。

こちらのファイルを下記のように変更します。

```php:NovelsTableSeeder.php
<?php

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

class NovelsTableSeeder extends Seeder
{

    public function run()
    {
        $tags = Tag::all();

        // factoryを利用
        factory(App\Novel::class, 100)
            ->create()
            ->each(function (App\Novel $novel) use ($tags) {
                //1~6までの数値をランダムで取得
                $ran = rand(1, 6);

                // 中間テーブルに紐付け
                $novel->tags()->attach(
                    //tagsテーブルからランダムで1~6個のインスタンスを紐づける。
                    $tags->random($ran)->pluck('id')->toArray(),
                   //attachの第二引数は他のカラムに挿入したい値を入れることができる。
                   //今回はtag_numberというカラムにランダムで1~6の数値を挿入。これは僕の都合上やってるだけなので、気にしなくてOK。
                    ['tag_number'=>$ran] 
                );
            });
    }
}
```

```php:TagsTableSeeder.php
<?php

use Illuminate\Database\Seeder;

class TagsTableSeeder extends Seeder
{
    public function run()
    {
        factory(App\Tag::class, 50)->create();
    }
}

```

上記の通りです。

多対多の中間テーブルへの紐付けは`attachメソッド`を使うのが基本です。
第一引数に紐づけるid、第二引数には他のカラムにも値を追加したい場合はその値を指定します。

今回の場合は`$novel->tags()->attach`とすることで、中間テーブルの`novel_idカラム`に`$novelのid`が保存されます。次に`tag_idカラム`の値を指定する必要があるので、`attachメソッド`内に記述します。

```
$tags->random($ran)->pluck('id')->toArray(),
```
`$tags`には`$tags = Tag::all();`で取得したtagsテーブルの全データが入っています。その中からランダムで1~6個のインスタンスを取得して、それらのidを配列にしています。`$ran`は`$ran = rand(1, 6);`の部分でランダムで1~6の値を挿入しています。

このようにしているのは、**小説には1~6個までのタグを指定できる**という設定にしているからです。
別に1つしかタグ付けしないなら、下記でOK。

```
$tags->random(1)->value('id'),
```

##3.作ったシーダーをコマンドで実行できるように登録する。

最後に`app > database > seeds > DatabaseSeeder.php`にて、今作ったシーダーを登録します。

```
<?php

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{

    public function run()
    {
        $this->call([
        TagsTableSeeder::class, //先にコッチ。
        NovelsTableSeeder::class,
    ]);
    }
}

```

先にタグのシーダーを記述しておかないとエラーになるので注意してください。

あとは下記コマンドを実行すればOkです。

```
php artisan db:seed
```


駆け足でしたが、これにて終了です。

factoryを使えば簡単に大量のデータを作れます。

慣れないうちは大変だと思いますが、ぜひ使ってみてください。