Monday, May 22, 2017

Laravel factory relationships... respect create() or make()

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!



via Johnny

Advertisement