52
42

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Laravelのfactory(faker)で3階層以上のテストデータを作る

Last updated at Posted at 2017-03-11

この記事は移行しました!最新の内容はこちらをご覧ください😀

Laravelのファクトリ便利ですよね。
fakerでテストデータ作るのもラクチンです。

ただ、User->Post->Commentのような3階層構造のリレーションモデルを作るときに悩みました。

結論

いろいろと試行錯誤した結果、今後はこのコードで作成しようと思います。

seederまたはtestcode
factory(User::class, 3)->create()->each(function ($user) {
    factory(Post::class, 2)->create(['user_id' => $user->id])->each(function ($post){
        factory(Comment::class, 3)->create(['post_id' => $post->id]);
    });
});

下記リレーション構造を持つUserが3つ出来上がります。

  • User
    • Post
      • Comment
      • Comment
      • Comment
    • Post
      • Comment
      • Comment
      • Comment

メリット

  • 書き方が統一されている
  • 何階層でもOK
  • 数値部分を変えれば各件数も思いのまま

デメリット

  • 親IDのカラム名漏れ(でも変更しないだろうし、テストコードだし、いいよね?)

経緯

いつもお世話になっているReaDoubleのサンプルコードを参考にしたのですが、いろいろ問題がありました。

サンプルコードでは2階層までは作れたが

ReaDoubleのsample
$users = factory(App\User::class, 3)->create()->each(function ($u) {
    $u->posts()->save(factory(App\Post::class)->make());
});
  • 親はcreate、子はmakeでわかりずらい
  • Postを複数作りたいときはsaveManyにしないといけない
    $user->posts()->saveMany(factory(Post::class, 2)->make());

3階層以上はどうすればいいのかわからなかった

試行錯誤したがエラーとなるコード
factory(User::class, 2)->create()->each(function ($user) {
    $user->posts()->saveMany(factory(Post::class, 2)->make()->each(function ($post) {
        $post->comments()->saveMany(factory(Comment::class, 2)->make());
    }));
});
  • 親IDがNULL的なエラーが発生する・・・。
    SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'post_id' cannot be null

ファクトリ定義の中で作成する方法もあったけど、、

ReaDoubleのsample
$factory->define(App\Post::class, function ($faker) {
    return [
        'title' => $faker->title,
        'content' => $faker->paragraph,
        'user_id' => function () {
            return factory(App\User::class)->create()->id;
        }
    ];
});
  • 常に親モデルをcreateすることになってしまう
  • そもそもファクトリ定義はモデル毎に分離しておきたい
  • 3階層以上だと出来てもカオスになりそう

ということで

冒頭のコードにたどり着きました。
他に良い方法がありましたら教えてください。

それではステキなLaravelライフを。

52
42
3

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
52
42

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?