ブログ名をここに記入

オンライン備忘録

Laravelで独自テーブル(migrateで作成していないテーブル)にSeederでテストデータを登録するまでのメモ

LaravelでFactory / Seederを利用してテストデータを利用する際 migration経由で作成していないテーブル等にもデータ投入ができるのか、検証した際のメモ。

検証内容

  1. 独自で作成したテーブルにSeederでデータを投入
  2. 命名規則に準じていないテーブルに対ししてSeederでデータを投入

環境

Laravel Framework 9.43.0 PHP 8.0.26

独自で作成したテーブル

①テーブルを作成

CREATE TABLE `test_users` (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
);

②Factory / Seeder / Modelを作成

# php artisan make:factory TestUserFactory

   INFO  Factory [database/factories/TestUserFactory.php] created successfully.

# php artisan make:seeder TestUsersTableSeeder

   INFO  Seeder [database/seeders/TestUsersTableSeeder.php] created successfully.  

# php artisan make:model TestUser

   INFO  Model [app/Models/TestUser.php] created successfully.  

TestUserFactory.php

<?php

namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;

/**
 * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Model>
 */
class TestUserFactory extends Factory
{
    /**
     * Define the model's default state.
     *
     * @return array<string, mixed>
     */
    public function definition()
    {
        return [
            'name' => $this->faker->name(),
        ];
    }
}

TaxRatesTableSeeder.php

<?php

namespace Database\Seeders;

use App\Models\TaxRate;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;

class TaxRatesTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        TaxRate::factory()
            ->count(3)
            ->create();
    }
}

DatabaseSeederも忘れず。

<?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(TestUsersTableSeeder::class);       
    }
}

TestUser.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class TestUser extends Model
{
    use HasFactory;
}

③seed実行

# php artisan db:seed

   INFO  Seeding database.  

  Database\Seeders\TestUsersTableSeeder .................................................................................................... RUNNING  

   Illuminate\Database\QueryException 

  SQLSTATE[42S22]: Column not found: 1054 Unknown column 'updated_at' in 'field list' (SQL: insert into `test_users` (`name`, `updated_at`, `created_at`) values (斉藤 淳, 2023-01-05 14:56:40, 2023-01-05 14:56:40))

なるほど。。 migrateなどでテーブル作成した際、自動的に付与される日付カラム(created_at / updated_at)がないと言われている。。

公式の資料を見る。何事も公式を見るべき。 Eloquentの準備 9.x Laravel

④モデルの$timestampsをfalseにする。

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class TestUser extends Model
{
    use HasFactory;

    /**
     * モデルにタイムスタンプを付けるか
     *
     * @var bool
     */
    public $timestamps = false;
}

⑤seed再挑戦

# php artisan db:seed

   INFO  Seeding database.  

  Database\Seeders\TestUsersTableSeeder .................................................................................................... RUNNING  
  Database\Seeders\TestUsersTableSeeder ............................................................................................. 379.76 ms DONE  

⑥結果確認

id name
1 テスト太郎
2 コレステロー太郎
3 山本 涼平
4 山口 直樹
5 加納 さゆり

3件ランダムデータが入りました。 (1と2は自分でINSERTしたテストデータです。既存データも消えませんね。)


命名規則から外れたテーブル

テーブル名は小文字スネークケース複数形が命名規則なんですが、そうじゃないテーブルを作ります。

①テーブルを作成

CREATE TABLE `TestShop` (
  `shopId` int NOT NULL AUTO_INCREMENT,
  `shopName` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`shopId`)
);

②Factory / Seeder / Modelを作成

# php artisan make:factory TestShopFactory

   INFO  Factory [database/factories/TestShopFactory.php] created successfully.  

# php artisan make:seeder TestShopsTableSeeder

   INFO  Seeder [database/seeders/TestShopsTableSeeder.php] created successfully.  

# php artisan make:model TestShop

   INFO  Model [app/Models/TestShop.php] created successfully.  

TestShopFactory.php

<?php

namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;

/**
 * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Model>
 */
class TestShopFactory extends Factory
{
    /**
     * Define the model's default state.
     *
     * @return array<string, mixed>
     */
    public function definition()
    {
        $shopNames = ['大阪店', '札幌店' , '名古屋店' , '広島店'];
        $idx = rand(0, 3);


        return [
            'shopName' => $shopNames[$idx],
        ];
    }
}

TestShopsTableSeeder.php

<?php

namespace Database\Seeders;

use App\Models\TestShop;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;

class TestShopsTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        TestShop::factory()
        ->count(3)
        ->create();
    }
}

DatabaseSeeder.phpも追記(コード略)

TestShop.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class TestShop extends Model
{
    use HasFactory;

    /**
     * モデルにタイムスタンプを付けるか
     *
     * @var bool
     */
    public $timestamps = false;
}

③seed実行してみる

# php artisan db:seed

   INFO  Seeding database.  

  Database\Seeders\TestShopsTableSeeder .................................................................................................... RUNNING  

   Illuminate\Database\QueryException 

  SQLSTATE[42S02]: Base table or view not found: 1146 Table 'db.test_shops' doesn't exist (SQL: insert into `test_shops` (`shopName`) values (広島店))

まぁ、そうなるよね。

③モデルを修正

結局ここに行き着く Eloquentの準備 9.x Laravel

「テーブル名」「主キー」のところを参考に。

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class TestShop extends Model
{
    use HasFactory;

    /**
     * モデルにタイムスタンプを付けるか
     *
     * @var bool
     */
    public $timestamps = false;

    /**
     * モデルに関連付けるテーブル
     *
     * @var string
     */
    protected $table = 'TestShop';

    /**
     * テーブルに関連付ける主キー
     *
     * @var string
     */
    protected $primaryKey = 'shopId';
}

④seedを再実行

# php artisan db:seed

   INFO  Seeding database.  

  Database\Seeders\TestShopsTableSeeder .................................................................................................... RUNNING  
  Database\Seeders\TestShopsTableSeeder ............................................................................................. 286.97 ms DONE  
shopId shopName
5 東京店
6 札幌店
7 大阪店
8 名古屋店

できた。


結論:公式ドキュメントを読めばわかる。