I am making raking system for my users and here’s what I have so far:
Get all users and sort them by points – it works fine.
$users = User::all(); $users = $users->sortByDesc(function($item){ return $item->points()->sum('amount'); });
Find your position in ranking – it works fine
$position = 0; foreach($users as $user){ if(Auth::user()->id == $user->id) break; $position++; }
Get myself and users above/under me – it doesn’t work. I get random users. It looks like the collection is not sorted anymore.
$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]); }
Please help me with this one or give some hint on another approach(light weight for many records)
Advertisement
Answer
I think the problem is this:
When you call User::all()
you get something like this:
0 => points: 10 1 => points: 50 2 => points: 30 3 => points: 70 4 => points: 20
Then you use the sortBy function, which reorder the collection, but does not reset the keys. So you end up with something like this:
3 => points: 70 1 => points: 50 2 => points: 30 4 => points: 20 0 => points: 10
So using position -1, position, and position +1 makes no sense here.
What you can do is using the values() function, which will reset the keys of you collection:
0 => points: 70 1 => points: 50 2 => points: 30 3 => points: 20 4 => points: 10
So I think the following code would work.
$users = User::all(); $users = $users->sortByDesc(function($item){ return $item->points()->sum('amount'); })->values();
And then get 3 users from positions – 1 to position + 1:
$myRank = $users->splice($position - 1, 3);