Search code examples
phplaravellaravel-5.4eager-loading

Eager Loading Multiple Associations In Laravel With A Condition On One Association


I've been trying to eager load a Forum model, but I also need a all the boards for that forum, as well as the most recent thread and the user that created that thread for each board. After extensive research, this has been my approach:

public function show($forum)
{

    $forumCol = Forum::with([
        'boards' => function($query) {
            return $query->with(['threads' => function($query) {
                 return $query->with('user')->latest()->first();
            }])->get();
        }
    ])->where('id', $forum)->first();

    return view('forum.forum', ['forum' => $forumCol]);
}

Yet no matter how many different variants of what I put above I try, I can't load neither the thread nor the user. When dd'ing the page with the $forum variable. I get a collection with the forum, and the associated boards, yet the thread is loading as an empty collection (hence I can't load the user).

Is my syntax incorrect for this eager load? I've been working on this for a couple hours and any help would be much appreciated.

Thanks

Edit: Sandeesh, that's what I thought as well, but I had already tried that and threads are still an empty collection. Also, just in case your wondering I've checked all of my relationships and they work perfectly. Here's a screenshot of the $forum collection:Image of $forum collection

If anyone is curious how I solved this, it is answered below.


Solution

  • This took me an awfully long time, but I finally found the answer! After plenty of research, I stumbled accross a website that suggested this approach:

    With the rest of your model relations:

    public function latestThread()
    {
        return $this->hasOne('ReadIt\Thread')->latest();
    }
    

    Then, instead of having a condition on one association, I could eager load simply like the following:

    $forumCol = Forum::with(
            'boards',
            'boards.latestThread',
            'boards.latestThread.user'
        )->where('id', $forum)
        ->first();
    

    When I saw this I was extremely skeptical at first. I tested it and it works though. You can use hasOne, even if the relationship is hasMany, and it will get the first one. Now I am not sure why you are able to organize afterwards to make sure you get the most recent thread, but it works!

    Hope this is helpful.