Laravel factory relationship ... respect create () or make ()
According to Laravel, the documentation for defining relationships in model factories is :
You can also attach relationships to models using Closure attributes in factory definitions. For example, if you want to create a new user instance when creating a Post, you can 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 problem I am facing is the reference to create()
in the definition of the relationship. It seems to me that this does not belong here.
This works great if I want to keep my relationship with the database:
factory(App\Post::class)->create();
By running the code directly above this, a new App\Post
and a new one will be created App\User
and both are stored in the database.
But if I just want to new
raise the model (s) and not save 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 instance App\Post
is created but not saved, but it App\Comment
is created and stored in the database.
It seems to me that I really want 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 relevant data to respect what I am trying to do from the top of the call, down. Do everything. Or create everything.
Am I doing something wrong here? Or is it something that does not currently exist?
Thank!
source to share
Try this approach
I had the same problem as yours, this solution worked for me but couldn't find the cause.
$factory->define(App\Post::class, function ($faker) {
return [
'title' => $faker->title,
'content' => $faker->paragraph,
'user_id' => function () {
$user = factory(App\User::class)->make();
$id = $user->id;
$user->save();
return $id;
}
];
});
source to share
You need a lazy () method for your sibling models!
At least in Laravel 5.5.
I found your question here because I had the same problem. I found the answer thanks to Laravel's nicely written code - lazy () was defined just above make () XDebug took me to - and I tried it and it seems to work.
This is what I am 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 it factory(App\Image::class)->lazy()->id
, but I can still see that it has successfully set the correct images_and_and_and_and_and_and_
I certainly hope you found a solution long before this, but maybe it will help someone else!
source to share