個人メモ。
詳しい解説は、最下部の参考記事から。
環境
- Laravel 10.4.1
- データベース MariaDB 5.5.68
- PHP 8.2.4
前提
-
User
テーブルとTodo
テーブルがあり、リレーションで1対多の関係(user1に対し、todoが複数)。 - この1対多の関係で整合性のあるテストデータを自動作成する。
作業
- todoSeeder作成
php artisan make:seeder todoSeeder
で \Laravelapp\database\seeders\todoSeeder.php 作成。
(userSeederは確か最初から存在)
- userモデルにリレーション追加
app/Models/User.php
// リレーション設定
public function todo(): HasMany
{
return $this->hasMany(Todo::class);
}
- todoモデルにリレーション追加
app/Models/Todo.php
// リレーション設定
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
// Faker(モデルファクトリ)でのインサートを許可するカラムを定義
protected $fillable = [
'user_id',
'title',
'todo',
'add_date',
'update_date',
];
- UserFactory.php のdefinition の初期状態(変更なし)
\database\factories\UserFactory.php
public function definition(): array
{
return [
'name' => fake()->name(),
'email' => fake()->unique()->safeEmail(),
'email_verified_at' => now(),
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
'remember_token' => Str::random(10),
];
}
- TodoFactory.php は下記のように記載
\database\factories\TodoFactory.php
use App\Models\User;
public function definition(): array
{
$date = $this->faker->dateTimeBetween('-1year');
return [
'user_id' => User::factory(),
'title' => $this->faker->realText(random_int(10, 20)),
'todo' => $this->faker->realText(random_int(30, 50)),
'add_date' => $date,
'update_date' => $date,
];
}
- 自動生成するデータを日本語にする
/config/app.php
のfaker_locale
を'ja_JP'にすると、自動生成されるデータが日本語になります。
app.php
/*
|--------------------------------------------------------------------------
| Faker Locale
|--------------------------------------------------------------------------
|
| This locale will be used by the Faker PHP library when generating fake
| data for your database seeds. For example, this will be used to get
| localized telephone numbers, street address information and more.
|
*/
// 'faker_locale' => 'en_US',
'faker_locale' => 'ja_JP',
- DatabaseSeeder.php に下記1行追加
\database\seeders\DatabaseSeeder.php
public function run(): void
{
$this->call(todoSeeder::class);
}
- todoSeeder.php を下記のようにする
\database\seeders\todoSeeder.php
use Illuminate\Database\Seeder;
use App\Models\User;
use App\Models\Todo;
public function run(): void
{
$users = User::factory(3)->create();
Todo::factory(30)->recycle($users)->create();
}
ここでのポイントはrecycleを使っているところで、これにより、todoテーブルのuser_idカラムに、あらかじめ作成したuserのランダムなidが入って、一対多のデータになる。
これで、user:todoの一対多のリレーションでのデータがランダムに追加できた。
上記のtodoSeederだと、userが3レコードに対し、todoが合計30作られ、userのいずれかに割り振られる。(3ユーザー合計で30todoレコードとなる)
→この場合、userSeeder.phpには何も追加で書かなくてよかった。
- ログインテスト時のパスワードについて
ちなみに自動生成されたUserテーブルのデータで、ログインテストをするときのパスワードは何になるのか?ハッシュ化された文字列が生成されるので元のパスワードがわからないはず、と疑問に思っていたが、UserFactoryに下記の記載があり、「password」がハッシュ化した文字列が生成されるので、テストでは「password」とすればログインできると気づいた(コメントが親切にハッシュ前文字列を示していたのだ)。
UserFactory.php
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
参考
LaravelのModel Factoryでリレーション関係のダミーデータを作る
LaravelのFakerとSeedingでダミーデータを自動生成しデータベースへ投入する
Laravelでテストデータ作成 ファクトリ・シーダ