如果外部 ID 作为属性传递,则防止在工厂中创建关系模型

Prevent creating relation model in factory if foreign id passed as attribute

让我们假设这个工厂:

PostFactory.php

$factory->define(Post::class, function (Faker $faker) {
    return [
        'title'=>$faker->word,
        'user_id'=>factory(User::class)->create()->id
    ];
});

然后我这样使用它:

$user = factory(User::class)->create();
factory(Post::class, 5)->create(['user_id'=>$user->id]);

我预计将创建 1 个用户和 5 个帖子。但实际上数据库中有 6 个用户,因为 PostFactory 创建用户,无论 user_id 是否通过。

如果 user_id 属性传递给 create 方法,有没有办法阻止创建新用户?

有一个解决方法。

$factory->define(Post::class, function (Faker $faker) {
    return [
        'title'=>$faker->word,
        'user_id'=> function () { return factory(User::class)->create()->id; }
    ];
});

Laravel 在合并属性时调用 value() 助手。如果user_id存在于属性中则不执行回调,否则执行

您可以在文档中看到它 here 与您的模型完全相同。

对于Laravel 5.1,您需要传递参数并手动检查是否传递了id。

这里是关于这个问题的讨论。 https://github.com/laravel/framework/issues/9245

$factory->define(App\User::class, function ($faker, $attributes) {

$accountId = isset($attributes['account_id']) ? $attributes['account_id']: factory(App\Account::class)->create()->id;

return [
    'account_id' => $accountId,
    'email' => $faker->email,
    'password' => 'secret',
    'name' => $faker->name
];

});