Back

Several Eager Loading with constraints


tzookb posted 3 years ago

I have this nice query:

$posts = Post::with('user','comments','comments.user', 'tags') ->take(10) ->orderBy('created_at', 'DESC') ->get();

now I would like to add a constraint to one of the eager loading tables. For this example to the comments.

In the link here: http://culttt.com/2013/12/30/eager-loading-laravel-4/

I see you place a array with key as the table name and the value as a callback, but when I do that like this:

$posts = Post::with('user',array('comments'=>function($query){echo 'doWhereHere';}),'comments.user', 'tags') ->where('travel_area_id','=',$area->id) ->take($this->numOfPostsInAreaPageLoad) ->orderBy('created_at', 'DESC') ->get();

I get this error: explode() expects parameter 2 to be string, array given

tzookb replied 3 years ago

I found a solution for my question , it's simply to concat the "with:

$posts = Post::with('user') ->with(array('comments.user'=>function($query){ $query->where('created_at', '=', 1); })) ->with('tags') ->where('travel_area_id','=',$area->id) ->take($this->numOfPostsInAreaPageLoad) ->orderBy('created_at', 'DESC') ->get();

but now I would like to have an eager load constraint on "comments.user" more specifically on the comments, and not on the user, any idea how, because the current where inflects the query for the user of the comment.

tzookb replied 3 years ago

AMAZING!!!!

found the solution, you should nest each one of the eager loads inside

$posts = Post::with('user')
     ->with(array('comments'=>function($query){
         $query->where('user_id', '=', 3);
         $query->with('user');
     }))
     ->with('tags')
     ->where('travel_area_id','=',$area->id)
     ->take($this->numOfPostsInAreaPageLoad)
     ->orderBy('created_at', 'DESC')
     ->get();
messerli90 replied 3 years ago

Hey bud, glad you could figure it out.

I don't mean to hijack your thread, but could you take a look at the post I made a couple hours ago because I think I'm struggling with a similar issue as this, but can't make sense of your answer right now.

http://laravel.io/forum/02-10-2014-creating-a-filter-for-results-from-relationships

zmorris replied 6 months ago

Alternative method using dot notation:

https://laracasts.com/discuss/channels/general-discussion/nested-eager-loading-with-constraints/replies/35385

When testing:

$query->with([
    'children' => function ($q) {
        $q->where('someCol', 'someVal'); //constraint on children
    },'children.grandchildren' => function ($q) {
            $q->where('someOtherCol', 'someOtherVal'); //constraint on grandchildren
    }
]);

Use:

dd($result->first()->children->first()->grandchildren->first());

NOT:

dd($result->first()->children()->first()->grandchildren()->first());

Note the parentheses which cause the relationships to be returned as queries instead of dynamic properties. Then first() gets called on a query instead of a collection, returning a fresh database response which doesn't have the specified constraints.

I was tearing my hair out trying to figure out why my where was being skipped until I spotted the extra parentheses.


Sign in to participate in this thread!



We'd like to thank these amazing companies for supporting us