web-dev-qa-db-ja.com

不要なモデルを作成せずに、モデルファクトリ、1対1および1対多の関係でLaravel外部キーを定義する

最近、私はLaravel ModelFactoryとFakerを介したシードを使用してデータベースをシードしようとしています。

単純なスキーマの場合、それを機能させるのは簡単です:)。ただし、外部キーとテーブルの関係を含む複雑なDBスキーマを操作するときに、いくつかの問題が発生しました。

  • 1対1
  • 1対多
  • 多対多

...リンクで説明されているもののように: モデルファクトリのLaravel 5.1外部キー

このトピックでは、 公式ドキュメント は次のようにデータベースシードを実行することを提案しています。

public function run()
{
    factory(App\User::class, 50)->create()->each(function ($u) {
        $u->posts()->save(factory(App\Post::class)->make());
    });
}

...しかし、このソリューションには1つの問題があります。多くのDBテーブルを操作し、(それらの間の関係が多い)多くのシードを実行する場合、多くの不要なモデルを作成するこの方法論を使用します。たとえば、上記の例の前にPostsTableSeeder.phpを実行した場合、それらの投稿はすべてユーザーにリンクされておらず、テストや開発で使用されることはありません...

したがって、この状況を処理する方法を探して、私は自分のために機能し、それらの「孤立した」モデルの不必要な作成を回避する機能的な解決策を思いつきました...

そして、私はそれをみんなと共有したかったので、それは答えで説明されています:)。

10
andcl

だからここに私の解決策があります:

この例では、次のことを扱います。

  • ユーザーとプロファイル1対1の関係を説明するため)
  • ユーザーと投稿1対多の関係を説明するため)

    // ONE TO ONE relationship (with Users already created)
    $factory->define(App\Profile::class, function (Faker\Generator $faker) {
        return [
            'user_id' => $faker->unique()->numberBetween(1, App\User::count()),
            // Rest of attributes...
        ];
    });
    
    // ONE TO MANY relationship (with Users already created)
    $factory->define(App\Posts::class, function (Faker\Generator $faker) {
        $users = App\User::pluck('id')->toArray();
        return [
            'user_id' => $faker->randomElement($users),
            // Rest of attributes...
        ];
    });
    
25
andcl

これは、特にこのモデルに追加情報を送信する必要がある場合に、ランダムなユーザーを割り当てるよりもはるかに優れた関係を作成するためのソリューションです。

$factory->define(App\Post::class, function (Faker\Generator $faker) {
    $user = factory('App\Models\User')->create(['email' => '[email protected]',]);
    // do your relationships here (...)
    return [
        'user_id' => $user->id,
        'title'   => $faker->sentence,
        'body'    => $faker->paragraph,
        ];
    }

そして、匿名関数を使用した別の例を見ました

$factory->define(App\Post::class, function (Faker\Generator $faker) {
    return [
        'user_id' => function () {
            return factory(App\User::class)->create()->id;
        },
        'title' => $faker->sentence,
        'body'  => $faker->paragraph,
    ];
}

出典: https://laracasts.com/series/laravel-from-scratch-2017/episodes/22

3
a20121248