Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Azoruk's avatar

Alternative to paginate on collection?

On my website, I have Submissions, and submissions can have comments.

Comments can have upvotes and downvotes, leading to a total "score" for the comment.

In this example, before passing the comments to the view, I sort them by score.

$comments = Comment::where('submission_id', $submission->id)->where('parent_id', NULL)->get();

$comments = $comments->sortByDesc(function($comment){
    return count($comment['upvotes']) - count($comment['downvotes']);
});     

This works fine. The higher the score of a comment, the higher it is sorted.

However, I want to paginate these results.

If I do ->paginate(10) instead get(), the following sortByDesc will only sort those 10 results.

So logically I would want to add the paginator after the sortByDesc like so:

$comments = $comments->sortByDesc(function($comment){
    return count($comment['upvotes']) - count($comment['downvotes']);
})->paginate(10);   

However this will return the error:

Method Illuminate\Database\Eloquent\Collection::paginate does not exist.

as expected.

My question is, what is the alternative to using paginate in this situation?

0 likes
9 replies
click's avatar

I don't know your exact implementation and on how many records we are talking about but can't you add a "cached" downvote/upvote on the comment it self? This way you can simply sort in your SQL query. That seems way more efficient. And your pagination question is resolved.

1 like
Azoruk's avatar

What do you mean cached? And potentially thousands of comments per submission, and potentially thousands of votes per comment.

jlrdw's avatar

potentially thousands of comments per submission, and potentially thousands of votes per comment.

Will attempt explaining. First it's not good to put thousands in a collection.

Second, kind of what click said, use your queries to get the data.

If user wants it sorted another way, use scopes. The "new" order by the scope will return.

Or for an easier solution, perhaps you could use data tables.

Enough said.

munazzil's avatar

Could be wrong in your index.blade.php check it was as like below because it could be after your getting data to frontend,

       {!! $comments->links() !!}
Snapey's avatar

You need to run the count and sort in the database so that you are plucking the top 10, then then next 10 from the database query and not do it from a laravel collection.

steve_laracasts's avatar

I agree with @click, store the 'score' and update it on each upvote or downvote; don't try and calculate the score at listing time - that's going to get out of hand really quickly!

aliya's avatar

you can use orderBy() method with your model or variable like ths $comment = Comment::orderBy('created_at','desc')->paginate(10);

Please or to participate in this conversation.