• 請求くん
  • Laravel

[Laravel]リレーション関係のダミーデータ作成(Factory, Seeder)

今回はリレーション関係にあるダミーデータの作成について書いていきたいと思います。

請求くんというアプリで実際に使用したものについて解説していきます。

前提

⚫︎テーブル

  • 掲載テーブル(postings)
  • 商品テーブル(products)

「postingsテーブル」に外部キーとして、"product_id"をもっています。
※下記の図を参照(みづらくてすんません...)

例えば「productsテーブル」の"id"が1〜4までしかないのに、「postingsテーブル」の"product_id"が10で作成とかはNGにしたいです。

⚫︎作成するデータ数

  • 「productsテーブル」はとりあえず4つだけ登録
  • 「postingsテーブル」は300件の登録をしたい

そのため今回は

  • 「productsテーブル」はseederで作成
  • 「postingsテーブル」はfactoryで作成

という流れで行っていきたいと思います。

商品(products)テーブルのデータ作成

前述のとおり、「productsテーブル」のデータ作成は、seederで行なっていきます。
個別にseederファイルを作成して、作成したいデータの数だけ手入力をするという方法です。

まずはseederファイルの作成

php artisan make:seeder ProductSeeder

database/seeders直下にProductsSeeder.phpのファイルが作成されました。

作成されたProductsSeeder.phpのrunメソッドの中身を記述します。

<?php

namespace Database\Seeders;

use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;  //DBファサードの読み込みを忘れないように

class ProductSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        DB::table('products')->insert([
            [
                'id' => 1,
                'name' => 'Aプラン 4週間',
                'base_price' => '28000',
            ],
            [
                'id' => 2,
                'name' => 'Bプラン 4週間',
                'base_price' => '41000',
            ],
            [
                'id' => 3,
                'name' => 'Cプラン 2週間',
                'base_price' => '40000',
            ],
            [
                'id' => 4,
                'name' => 'Dプラン 2週間',
                'base_price' => '56000',
            ]
        ]);
    }
}

一旦ここまでで準備完了とします。

掲載(postings)テーブルのデータ作成

「productsテーブル」のデータ作成は、factoryで行なっていきます。
300件作成したいので、先ほどの「productテーブル」のやり方ではとても書ききれないですね…
なので、指定したデータ数を一気に作成してくれるfactoryを使用します。

factoryファイルの作成

php artisan make:factory PostingFactory

database/factories直下にPostingFactory.phpが作成されました。

作成されたPostingFactory.phpの中身を記述します。

<?php

namespace Database\Factories;

use App\Models\Product;
use Illuminate\Database\Eloquent\Factories\Factory;

/**
 * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Posting>
 */
class PostingFactory extends Factory
{
    /**
     * Define the model's default state.
     *
     * @return array<string, mixed>
     */
    public function definition()
    {
        // ①productsテーブルのidを配列で取得
        $productIds = Product::pluck('id')->toArray();

        return [
            // ①で取得したidの配列をランダムに設定
            'product_id' => $this->faker->randomElement($productIds),

            // ここから下はpostingsテーブルの別カラムの記述
            'posting_term' => $this->faker->numberBetween(1, 4),
            'quantity' => $this->faker->numberBetween(1, 4),
            'price' => $this->faker->numberBetween(28000, 300000),
            'note' => $this->faker->optional(0.3)->realText(),
        ];
    }
}

「productsテーブル」のidを配列で取得 → その配列の中身をランダムに設定する
というだけのものです、はい。

テストデータの作成実行

seederとfactoryの設定が完了しましたので、最後にテストデータの作成をしていきます。

database/seeders直下にDatabaseSeeder.phpというファイルが元々あります。
そのファイルに先ほど作成したProductSeeder.phpやPostingFactoryを実行するためのコードを書きます。

<?php

namespace Database\Seeders;

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

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        $this->call([
            UserSeeder::class,
            ProductSeeder::class,  // ProductSeederの実行
        ]);
        Posting::factory(300)->create();  // PostingFactoryの実行
    }
}

ここで書く順番に注意が必要です。

今回の場合だと、PostingFactoryで「productsテーブル」のidを取得してました。
そのためProductSeederを先に実行しないと、PostingFactoryの実行の際に「productsテーブル」のidの取得ができませんというエラーがでてしまいます。
なのでProductSeederが先に実行されるように先に記述します。

最後にテストデータを作成するためにコマンドを実行します。

php artisan migrate:fresh --seed

migrate:freshをするとテーブルの再構築もされます。
テーブルの再構築は不要という場合には、migrate:refreshを実行してください。

以上でダミーデーターの作成がされました。お疲れ様でした!