LoginSignup
6
6

More than 3 years have passed since last update.

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

Posted at

今回は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.phpTagFactory.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,
    ];
});


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.phpTagsTableSeeder.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] 
                );
            });
    }
}
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を使えば簡単に大量のデータを作れます。

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

6
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6