mstnorris's avatar

How do I paginate a **Posts** **Replies**

I have implemented pagination on my forum index page which lists groups of 12 posts along with details about each one including number of replies etc.

I want to be able to paginate the replies when I view a certain post.

What is the Eloquent (or query) that will allow me to achieve this? So far I have this but it throws an error.

public function show($id)
    {
        $post = Post::with('replies')->paginate(12)->find($id);

        return view('posts.show', compact('post'));
    }
0 likes
17 replies
toniperic's avatar

@mstnorris something like this?

$post = Post::with('replies', function($query){
    return $query->paginate(12); // or whatever
})->find($id);
mstnorris's avatar

How do I get the Replies pagination links to render?

{!! $post->render() !!}

and

{!! $post->replies->render() !!}

Don't work, I'm sure I am doing something simple, wrong.

toniperic's avatar

@mstnorris given that you have access to thread id, couldn't you do this:

$replies = Reply::where('thread_id', $id)->paginate(12);

And then just do

$replies->render();

Please note when you call the paginate() method on the model, since it doesn't exist on the model it will be automagically called on the Query Builder instance, which returns LengthAwarePaginator instance. So that's why you can't call the render() method directly, like so:

$post->replies->render()

because $post->replies returns results from your HasMany relationship, and you can't call the render() method on it.

JarekTkaczyk's avatar

@mstnorris

$post = Post::find($id);
$replies = $post->replies()->paginate(12);

$replies->render(); // will work
mstnorris's avatar

@toniperic I could do that, but because I am showing the Post as well as a list of replies (hopefully a paginated list) then it makes sense to get the replies of the thread, not the replies and its associated thread. Does that make sense?

JarekTkaczyk's avatar
Level 53

@mstnorris It does exactly the same as long as we talk about the db:

$post = Post::with('replies')->find($id); // 2 queries

$post = Post::find($id); // 1st query
$replies = $post->replies()->paginate(12); // 2nd query
mstnorris's avatar

@JarekTkaczyk so the

$replies = $post->replies()->paginate(12); // 2nd query

is 'calculated' (so to speak) from the set of results?

JarekTkaczyk's avatar

@mstnorris Not at all. Have in mind the difference between relation and relation():

$post->replies; // fetches ALL the related rows and returns the collection
$post->replies(); // does not fetch anything yet, returns Relation Object that you can query

That said:

$post->replies()->paginate(12); // ordinary pagination query with limit 12
mstnorris's avatar

Ok, I think I understand. I'll have to do some more reading around that. I guess that will happen when you publish your book (which I am eagerly waiting - excuse the pun, it was unintentional).

The pagination is being shown, however, I am only seeing the same 12 replies on each page. Is that to be expected, am I missing something specific in my view?

mstnorris's avatar

Even with the paginate(12) method I am seeing all replies. So if there are 20 replies, I can see that there are two pages, but all 20 replies are shown on each page.

public function show($id)
    {
        $post = Post::with('replies')->find($id);
        $replies = $post->replies()->paginate(12);

        return view('posts.show', compact('post', 'replies'));
    }

Is the above correct?

JarekTkaczyk's avatar

@mstnorris Ain't you calling something like this in your view?

foreach ($post->replies as $reply) ...

You need to use $replies variable passed from the controller.

@nolros 4-6 weeks. I suppose some parts will be released sooner if you want me to ;)

mstnorris's avatar

@JarekTkaczyk yes I caught that this morning. I was doing

The Wrong Way

public function show($id)
    {
        $post = Post::with('replies')->find($id);
        $replies = $post->replies()->paginate(12);

        return view('posts.show', compact(['post', 'replies']));
    }

and accessing them in my view as

@foreach ( $post->replies as $reply )

instead of the correct answer

The Right Way

public function show($id)
    {
        $post = Post::find($id);
        $replies = $post->replies()->paginate(12);

        return view('posts.show', compact('post', 'replies'));
    }

and accessing them in my view as

@foreach ( $replies as $reply )

Please or to participate in this conversation.