使用模型工厂、一对一和一对多关系定义 Laravel 外键,而无需创建不必要的模型

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/40829086/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 14:49:40  来源:igfitidea点击:

Defining Laravel foreign keys with Model Factories, One to One & One to Many Relationships without creating unnecessary models

phplaravellaravel-5fakerlaravel-seeding

提问by andcl

Recently I have been trying to seed my database using Laravel seeding through Model Factories and Faker.

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

For simple schemas, it is just a breeze to have it working :). However, I have encountered several problems when working with complex DB schemas which involve foreign keys and table relationships:

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

  • One to One
  • One to Many
  • Many to Many
  • 一对一
  • 一对多
  • 多对多

...Like the one described in the link: Laravel 5.1 foreign keys in model factory.

...就像链接中描述的那样: 模型工厂中的 Laravel 5.1 外键

In this topic, the official documentationsuggests to run the database seeds like this:

在本主题中,官方文档建议像这样运行数据库种子:

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

... but there is one problem with this solution: when working with many DB tables and running many seeds (with many relations between them), it is common to create many unnecessary modelsusing this methodology. For instance, if we had run the PostsTableSeeder.php before the one of the above example, all those posts would not have been linked to users, and would never be used in tests and development...

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

So searching for a way to handle this situation, I have come up to a functional solution that works for me and avoids the unnecessary creation of those 'orphan' models...

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

And I wanted to share it with everyone, so it is just explained in the answer :).

我想与大家分享它,所以它只是在答案中解释:)。

回答by andcl

So here is my solution:

所以这是我的解决方案:

The example deals with:

该示例涉及:

  • Users & Profiles(for illustrating One to Onerelationships)
  • Users & Posts(for illustrating One to Manyrelationships)

    // 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...
        ];
    });
    
  • 用户和配置文件(用于说明一对一关系)
  • 用户和帖子(用于说明一对多关系)

    // 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...
        ];
    });
    

回答by a20121248

Here is a solution to make relationships that is way better than assigning random Users, especially if you need to send extra information to this model.

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

$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,
        ];
    }

And I saw another example with the use of anonymous function

我看到了另一个使用匿名函数的例子

$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,
    ];
}

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

来源:https: //laracasts.com/series/laravel-from-scratch-2017/episodes/22