2015-04-15 3 views
5

Я делаю систему сгребания для моих пользователей, и вот что у меня до сих пор:Laravel коллекция сортировки, а затем по ключевым

Получить все пользователи и сортировать их по точкам - это отлично работает.

$users = User::all(); 
$users = $users->sortByDesc(function($item){ 
    return $item->points()->sum('amount'); 
}); 

Найдите свою позицию в рейтинге - это прекрасно работает

$position = 0; 
foreach($users as $user){ 
    if(Auth::user()->id == $user->id) break; 
    $position++; 
} 

Получить себя и пользователей выше/под меня - это не работает. Я получаю случайных пользователей. Похоже, что коллекция больше не сортируется.

$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]); 
} 

Пожалуйста, помогите мне с этим или дать некоторый намек на другой подход (легкий вес для многих записей)

ответ

10

Я думаю, что проблема заключается в следующем:

Когда вы звоните User::all() вы получите что-то вроде это:

0 => points: 10 
1 => points: 50 
2 => points: 30 
3 => points: 70 
4 => points: 20 

Затем вы используете функцию sortBy, которая переупорядочивает коллекцию, но не сбрасывает ключи. Итак, у вас получилось что-то вроде этого:

3 => points: 70 
1 => points: 50 
2 => points: 30 
4 => points: 20 
0 => points: 10 

Так что использование положения -1, позиции и положения +1 здесь не имеет смысла.

Что вы можете сделать, используя значения функции(), который сбросит ключи вам коллекции:

0 => points: 70 
1 => points: 50 
2 => points: 30 
3 => points: 20 
4 => points: 10 

Так что я думаю, что следующий код будет работать.

$users = User::all(); 
$users = $users->sortByDesc(function($item){ 
    return $item->points()->sum('amount'); 
})->values(); 

А затем получить 3 пользователей из позиций - 1 в положение + 1:

$myRank = $users->splice($position - 1, 3); 
+0

Я думаю, что вы можете расширить класс коллекции затем вызвать ksort на массиве подложки , Очень грязный хак, хотя – peter

0

Для любой сортировки array по key, я хотел бы предложить родной PHP functionksort().

5

Для сортировки по ключу вы можете получить базовый массив, а затем снова создать коллекцию.

$c = collect(['a' => 1, 'c' => 67, 'b' => 2]); 
$items = $c->all(); 
ksort($items); 

$c = collect($items); 

Или вы можете использовать макрос, чтобы получить доступ к массиву подложки.

Collection::macro('ksort', function(){ 
    //macros callbacks are bound to collection so we can safely access 
    // protected Collection::items 
    ksort($this->items); 

    return $this; 
}); 

Последнее решение может быть очень полезно, если вы собираетесь нужно сортировать коллекции по ключу во многих местах в программном коде

+0

Этот вопрос уже дан. Два года назад. – zarcel

+8

@zarcel пока он появляется в google, это не только для вашей выгоды. – ash

+0

Согласен, даже если вопрос больше не имеет отношения к интересующемуся, кто-то может найти ответы полезными. Кроме того, через два года могут появиться новые решения. – Dragas

Смежные вопросы