Laravel模型工厂中的make()绕过create()在外键对象创建中。

huangapple go评论78阅读模式
英文:

Laravel model factory make() bypass create() in foreign key object creation

问题

我有一个用于Customer类的工厂

$factory->define(Customer::class, function (Faker $faker) {
    return [
        'hotel_id' => function() {
            return factory(\App\Hotel::class)->create()->id;
        },
        'name' => $faker->name,
        'phone' => $faker->phoneNumber,
        'email' => $faker->email,
    ];
});

对于调用factory(Customer::class)->create(),它运行正常。

但是,如果我想使用factory(Customer::class)->make()来在内存中创建Customer对象以传递给单元测试,这个工厂将创建一个Hotel对象并持久化到我的数据库中。

是否有一种模式可以帮助Laravel识别factory make(),并在生成对象时使用不同的方法。比如当我调用factory(Customer::class)->make()时,它会生成:

'name' => $faker->name,
'phone' => $faker->phoneNumber,
'email' => $faker->email,

然后它会创建一个$hotel = factory(Hotel::class)->make(),并执行$customer->setRelation('hotel', $hotel)

英文:

I have a factory for Customer class

$factory->define(Customer::class, function (Faker $faker) {
    return [
        'hotel_id' => function() {
            return factory(\App\Hotel::class)->create()->id;
        },
        'name' => $faker->name,
        'phone' => $faker->phoneNumber,
        'email' => $faker->email,
    ];
});

It's working fine for calling factory(Customer:class)->create().
However, if I want to factory(Customer:class)->make() to create Customer object in memory to pass to unit tests, this factory will create a Hotel object and persist to my database.

Is there a pattern that helps Laravel to recognize factory make(), and use a different approach when generating objects. Like when I call factory(Customer:class)->make(), it will generate

'name' => $faker->name,
'phone' => $faker->phoneNumber,
'email' => $faker->email,

THEN it will create a $hotel = factory(Hotel:class)->make() and do $customer->setRelation('hotel', $hotel) ?

答案1

得分: 1

你应该将 hotel_id 从工厂的 define 中排除,并改用后续回调函数。

根据文档(我的重点):

工厂回调使用 afterMakingafterCreating 方法进行注册,允许您在创建或制作模型后执行其他任务。例如,您可以使用回调将其他模型关联到已创建的模型

示例

$factory->afterMaking(App\User::class, function ($user, $faker) {
    // ...
});

$factory->afterCreating(App\User::class, function ($user, $faker) {
    $user->accounts()->save(factory(App\Account::class)->make());
});

https://laravel.com/docs/6.x/database-testing#factory-callbacks

英文:

You should keep the hotel_id out of the factory define and use the after callbacks instead.

From the documentation (my emphasis):

> Factory callbacks are registered using the afterMaking and
> afterCreating methods, and allow you to perform additional tasks after
> making or creating a model. For example, you may use callbacks to
> relate additional models to the created model
:

Example

$factory->afterMaking(App\User::class, function ($user, $faker) {
    // ...
});

$factory->afterCreating(App\User::class, function ($user, $faker) {
    $user->accounts()->save(factory(App\Account::class)->make());
});

https://laravel.com/docs/6.x/database-testing#factory-callbacks

huangapple
  • 本文由 发表于 2020年1月3日 16:45:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/59575474.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定