LoginSignup
0
0

More than 1 year has passed since last update.

Laravelのfactoryとseederで1対多関係のテーブルのテストデータを自動作成

Last updated at Posted at 2023-04-17

個人メモ。
詳しい解説は、最下部の参考記事から。

環境

  • 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.phpfaker_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でテストデータ作成 ファクトリ・シーダ

データベース:シーディング 10.x Laravel
マイグレーション 10.x Laravel

0
0
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
0
0