Laravel sort collection and then by key
Stefan Bogdanescu
Founder & Senior Architect · 2026-06-29
Ranking users based on their scores is an essential feature in various applications. In this blog post, we'll discuss how to efficiently sort a collection of users by points and extract specific positions without losing the sort order. We will also introduce the concept of pagination for better performance when dealing with large data sets.
Sorting Users By Points
To begin, let's sort all users based on their individual point sums:php
$users = User::all();
$users = $users->sortByDesc(function($item){
return $item->points()->sum('amount');
});Finding One's Position
To find your position in the ranking, we iterate through the sorted collection and search for your ID. Once found, we increment a counter until we reach your position, while making sure not to include any ties:php
$position = 0;
foreach($users as $user){
if(Auth::user()->id == $user->id) break;
$position++;
}Getting Your Position and Surrounding Users
Now that we know our rank, let's get ourselves and ten users above or under us:php
$myRank = new Collection();
if($position > 9){
$myRank->add($users->get($position-1));
$myRank->add($users->get($position));
$myRank->add($users->get($position+1));
return view('rank.show', ['topTen' => $users->take(15), 'myRank' => $myRank]);
}Better Approach with Laravel Collections
To efficiently rank users without losing the sorted order, we'll use Laravel collections and pagination: First, let's get all the users while maintaining their relative positions in a collection:php
$users = User::all();
$users = $users->sortByDesc(function($item){
return $item->points()->sum('amount');
});php
$users = new LengthAwarePaginator($users);
$topTen = $users->paginate(10);php
$position = 0;
foreach ($users as $user) {
if (Auth::user()->id == $user->id) break;
$position++;
}
if($position > 9 && $position < $topTen->total() + 10){
return view('rank.show', ['users' => $topTen, 'myRank' => $topTen->forPage(round((float) ($position - 1) / 10) + 1)]);
} elseif($position <= 9) {
return view('rank.show', ['users' => $topTen->slice(0, $position), 'myRank' => new Collection([$users->get($position-1), $users->get($position), $users->get($position+1)]), 'next' => $topTen->slice($position)]);
} else {
return view('rank.show', ['users' => $topTen, 'myRank' => new Collection([$users->get($position-10), $users->get($position-9), $users->get($position-8)]), 'prev' => $topTen->slice(0, $position - 10)]);
}