Rickkwa
Rickkwa

Reputation: 2291

Laravel eager loading with constraints

So my model has 2 simple relationships. Then eager loading works perfectly like this:

Entry::with('author', 'lastModifiedBy')->...;

But say I want to add a new relationship that takes a constraint. For example:

public function foo() {
    return $this->hasOne('Foo')->latest('id');
}

Then to eager load this relationship, Laravel suggests doing it like so:

Entry::with(array('foo' => function($query) use ($id) {
    $query->where('user_id', $id);
}))->...;

But if I want to include my author and lastModifiedBy relationships, I end up having to do:

Entry::with(array(
    'foo' => function($query) use ($id) {
        $query->where('user_id', $id);
    },
   'author' => function() { },
   'lastModifiedBy' => function() { }
))->...;

I have to give those 2 relationships an empty function. Is there a simpler way to do this without the ugliness of these empty functions?

Upvotes: 0

Views: 4351

Answers (2)

Sushant Aryal
Sushant Aryal

Reputation: 3335

You don't neew those empty functions. You can directly put the relations on them.

Entry::with(array(
    'foo' => function($query) use ($id) {
        $query->where('user_id', $id);
    },
    'author', 'lastModifiedBy'
))->...;

Or alternatively you can put those on nested with method.

Entry::with(array(
    'foo' => function($query) use ($id) {
        $query->where('user_id', $id);
    }
))
->with('author', 'lastModifiedBy')->...;

Upvotes: 1

lukasgeiter
lukasgeiter

Reputation: 152890

The empty functions are not necessary. Laravel is smart enough to be able to work with a mixed array of relations with constraints and such without them.

Entry::with(array(
    'foo' => function($query) use ($id) {
        $query->where('user_id', $id);
    },
    'author',
    'lastModifiedBy'
))->...;

How it works

Here's how Laravel distinguishes between the two:

in Illuminate\Database\Eloquent\Builder@parseRelations

foreach ($relations as $name => $constraints)
{
    // If the "relation" value is actually a numeric key, we can assume that no
    // constraints have been specified for the eager load and we'll just put
    // an empty Closure with the loader so that we can treat all the same.
    if (is_numeric($name))
    {
        $f = function() {};
        list($name, $constraints) = array($constraints, $f);
    }

As the comment describes, Laravel actually adds the empty closure by itself if the key of the array item is numeric.

Upvotes: 6

Related Questions