According to Laravel's documentation on defining relationships within model factories:
You may also attach relationships to models using Closure attributes in your factory definitions. For example, if you would like to create a new User instance when creating a Post, you may do the following:
$factory->define(App\Post::class, function ($faker) {
return [
'title' => $faker->title,
'content' => $faker->paragraph,
'user_id' => function () {
return factory(App\User::class)->create()->id;
}
];
});
The issue I'm running into is the reference to create()
within the relationship definition. It seems to me that this doesn't belong here.
It works great if I am wanting to persist my relationships to the database:
factory(App\Post::class)->create();
By running the code directly above this, a new App\Post
and a new App\User
will be created and both persisted to the database.
But if I just want to new
up the model(s) and not persist anything (at all) to the database by running:
factory(App\Post::class)->make();
It does what I want up to a certain point. A new App\Post
instance is created but not persisted, however App\Comment
is created and is persisted to the database.
It seems to me, that what I really want is something like this:
$factory->define(App\Post::class, function ($faker) {
return [
'title' => $faker->title,
'content' => $faker->paragraph,
'user_id' => function () {
// here I only want to declare the relationship,
// not decide whether I want to create() or make()
// the relationship, something like:
return factory(App\User::class)->createOrMake()->id;
// or perhaps something like:
return factory(App\User::class)->id;
}
];
});
The end result is that I want the related data to respect what I'm trying to do from the top of the call, down. Make everything. Or create everything.
Am I doing something wrong here? Or is this something that doesn't currently exist?
Thanks!
You want the lazy() method for your related models!
At least in Laravel 5.5.
I found your question here because I was having the same issue. I found the answer thanks to Laravel's beautifully written code -- lazy() was defined just above the make() XDebug took me to -- and I've tried it out and it seems to work.
This is what I'm doing:
$factory->define(App\ArtItem::class, function (Faker $faker) {
return [
// 'id' => $faker->randomDigit,
'slug' => $faker->unique->word,
'artist_id' => factory(App\Artist::class)->lazy(),
'image_id' => factory(App\Image::class)->lazy(),
'created_at' => $faker->dateTime,
'updated_at' => $faker->dateTime,
'deleted_at' => $faker->dateTime,
];
});
Lazy() is an interesting creature that returns a closure, so you can't do factory(App\Image::class)->lazy()->id
but I'm still seeing it successfully setting the correct image_id and artist_id.
I certainly hope you found the solution long before this, but maybe this'll help someone else!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With