Laravelで独自テーブル(migrateで作成していないテーブル)にSeederでテストデータを登録するまでのメモ
LaravelでFactory / Seederを利用してテストデータを利用する際 migration経由で作成していないテーブル等にもデータ投入ができるのか、検証した際のメモ。
検証内容
- 独自で作成したテーブルにSeederでデータを投入
- 命名規則に準じていないテーブルに対しして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 | 名古屋店 |
できた。