LaravelのSeederを利用して、テストデータを生成する方法（1対多, 多対多）

# テストデータを生成したい！！
テストデータを生成しておけば、リストをいちいち生成しないでいいので非常に楽になります。

Seederの書き方はパターンがあるので、今回は技術の棚卸しとして、Seederの書き方をアウトプットして整理しておきたいと思います。


「では、早速やっていきましょう！！」


# 1対多
1対多の場合はシンプルにリレーションを使って作成します。

```php:リレーションでcreate()
$post->likes()->create([
    'user_id' => $users[array_rand($users)],
]);
```
これで$postの子モデルであるlikeモデルをcreateします。
いいね！機能の場合は、複数のいいねを生成したいので、下記のような例になります。


```php:いいねをseederで作成する例
<?php

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

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

        $posts = App\Models\Post::all();
        $users = App\User::pluck('id')->all();
        /* $postsを繰り返し処理を実施する。ただし$usersは複数系で利用したいので、useでそのまま利用する。 */
        $posts->each(function ($post) use ($users) {
            /* rand($min, $max) で、一つの$postに対して10~1000個のいいねを生成する */
            for ($count = 0; $count < rand(10, 1000); $count++) {
                $post->likes()->create([
                    /* array_randで$usersの中からランダムで1つ取得する */
                    'user_id' => $users[array_rand($users)],
                ]);
            }
        });
    }
}
```

## createMany()で生成する場合

```php:コメントを生成する場合
<?php

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

class StrengthAppealTextSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $post = Post::find(1);
        $post->comments()->createMany([
            [
                "text" => "これだとどれに紐づいてるかパッとみてわかるよねえ"
            ],
            [
                "text" => "みやすい場合もあるよねえ"
            ],
            [
                "text" => "これが投稿されるよ。"
            ],
        ]);
    }
}
````

# 多対多 
多対多のSeederはどうすればよいでしょうか？
少し悩みどころですよね。
ここでは、例を紹介していきます


## リレーションを活用する方法
リレーションを呼び出して、create()する方法があります。

```php:例
$tableA->tableBs()->create([
  "text" => "aaaa"
]);
```
こんな感じでリレーションを活用して、紐ける方法があります。
少し具体的に見てみましょう。

````php:具体例
/* Factoryを利用してランダムに生成 */
$As = TableA::all();

/* 複数得られた$Asに対して、それぞれTableBを紐付ける*/
foreach ($As as $A) {
   $A->questions()->saveMany(factory(TableB::class, 15)->create()); //createManyでもできます
}

````
多対多はsaveMany, createMnayで一括で作成することができます。生成する中身をfactoryで定義しておけばこれだけで作成できます。

## 中間テーブルをfactoryで生成する方法
多対多なので、中間テーブルにランダムにIDを紐づけて、多対多の情報を作成する方法です。
「Seederで複雑な処理はせずに,factoryで外部キーを設定して作成すれば簡単じゃない？」というやり方です。



````php:複数タグの例：PostTagFactory.php
<?php

/** @var \Illuminate\Database\Eloquent\Factory $factory */

use App\Models\post_tag;
use App\Models\Post;
use Faker\Generator as Faker;

$factory->define(post_tag::class, function (Faker $faker) {
    /* 中間テーブルに紐付けるIDを取得する*/
    $postIDs  = App\Models\Post::pluck('id')->all();
    $tagIDs  = App\Models\Tag::pluck('id')->all();

    /* 中間テーブルを作成する*/
    return [
        'post_id' => $faker->randomElement($postIDs), // ランダムでIDを選択
        'tag_id' => $faker->randomElement($tagIDs)    // ランダムでIDを選択
    ];
});
````

あとはSeederを実行して、生成します。

````php:PostTagSeeder.php
<?php

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

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

# 最後に
いかがだったでしょうか
実例を交えたので、非常に参考になったのではないでしょうか？
内容が面白かった！！参考になった！！という方は

### LGTMをお願い致します<_ _>
LGTMもらえるとルンルン♪になるんですよね
超励みになります
めっちゃ待ってます
LGTMくださあああああああああああああい