【问题标题】:Defining Laravel foreign keys with Model Factories, One to One & One to Many Relationships without creating unnecessary models使用模型工厂、一对一和一对多关系定义 Laravel 外键,而不创建不必要的模型
【发布时间】:2017-04-11 06:39:06
【问题描述】:

最近我一直在尝试通过 Model Factories 和 Faker 使用 Laravel 播种来播种我的数据库。

对于简单的模式,让它工作起来很容易:)。但是,在处理涉及外键和表关系的复杂数据库模式时,我遇到了几个问题:

  • 一对一
  • 一对多
  • 多对多

...就像链接中描述的那样: Laravel 5.1 foreign keys in model factory.

在本主题中,official documentation 建议像这样运行数据库种子:

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

...但是这种解决方案存在一个问题:当使用许多数据库表并运行许多种子(它们之间有许多关系)时,通常会使用此方法创建许多不必要的模型方法。例如,如果我们在上述示例之前运行 PostsTableSeeder.php,那么所有这些帖子都不会链接到用户,并且永远不会用于测试和开发......

所以在寻找处理这种情况的方法时,我想出了一个适合我的功能性解决方案,并避免不必要地创建那些“孤儿”模型......

我想和大家分享一下,所以只是在答案中解释了:)。

【问题讨论】:

    标签: php laravel laravel-5 faker laravel-seeding


    【解决方案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...
          ];
      });
      

    【讨论】:

    • 我不认为您可以建议为多对多关系实现相同目标的最佳方法?我有带有 User_Cases 表的用户和案例来解决多对多问题。我正在尝试编写一个工厂来播种我的数据库。
    • 我在播种机而不是工厂中获得 多对多 方法...在播种机中,您只需检索两个模型(用户Cases)并循环遍历其中一个,并在每种情况下分配另一个。
    【解决方案2】:

    这是一种建立关系的解决方案,它比分配随机用户要好得多,尤其是当您需要向该模型发送额外信息时。

    $factory->define(App\Post::class, function (Faker\Generator $faker) {
        $user = factory('App\Models\User')->create(['email' => 'email@test.com',]);
        // 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

    【讨论】:

    • 这里使用匿名函数是正确的做法。如果您没有像第二个示例所示将用户的创建放在匿名函数中,那么每次调用工厂的 create/make 方法时都会创建一个新的 User 模型。如果您将现有用户的user_id 传递给工厂方法,它仍然会创建一个新用户,即使帖子不会附加到它(它将附加到您提供的 user_id)。通过使用第二个示例中的匿名函数,它只会在您不向其提供 user_id 时创建一个新用户。
    猜你喜欢
    • 2018-08-11
    • 2017-03-21
    • 1970-01-01
    • 2011-11-15
    • 1970-01-01
    • 2019-06-21
    • 2021-03-02
    • 2023-02-12
    • 1970-01-01
    相关资源
    最近更新 更多