DoeJohn's avatar

Paginate Constrained Eager Load?

I have the following relations:

  • Forum hasMany Thread
  • Thread hasMany Post
  • Post belongsTo User

There is a page for listing of the forums and I have the following code:

        $forums = Forum::with(['threads' => function ($query) {   // Eager load latest threads
                $query->approved()->latest()
                    ->with(['posts' => function ($query) {   // Eager load latest posts
                        $query->with('user')->approved()->latest()->paginate(10);   //<---- PAGINATE
                }]);
            }])
            ->get();

As you can see, I eager-load threads with constraints in which I also eager-load posts (also with constraints) which are paginated.

Everything works OK except pagination of posts. The reason why I want to paginate is because I want to be able to use the paginator instance methods in order to be able to generate a link to the latest page (post) of thread.

But ->paginate(10) doesn't work, posts are not paginated but there are no errors. For example, in my controller if I do:

        foreach ($forums as $forum) {
            dd($forum->threads->first()->posts);
        }

... the result will not be LengthAwarePaginator but Collection. Am I doing something wrong or this isn't possible?

I am using Laravel 5.4.

0 likes
2 replies
Talinon's avatar
Talinon
Best Answer
Level 51

I don't think you can paginate eager loaded constraints like this.

I speak about something similar here: https://www.laracasts.com/discuss/channels/laravel/how-to-use-paginate-when-filter-is-used

There may be a better way, but this would give you the result you're after. It may not be the most efficient or prettiest, but you should be able to use this to map over posts and convert them to the LengthAwarePaginator class.

Something like:

    $forumsWithPaginatedPosts = $forums->map(function($forum) {

        return $forum->threads->map(function ($thread) {

            $thread->paginatedPosts = $this->paginate($thread->posts, 10);

            return $thread;

        });

    });

Taking your blade code, you could then access your paginated posts via

foreach ($forums as $forum) {
    dd($forum->threads->first()->paginatedPosts);
}
1 like

Please or to participate in this conversation.