Laravel 5 – многомерная группаBy, orderBy & paginate

У меня есть модель Post, и я пытаюсь ->paginate() , ->groupBy() и ->orderBy() .

 public function index() { $posts = Post::where('verified', '1') ->orderBy('created_at','desc') ->groupBy('topic', 'publisher_id') ->paginate(5); // dd($posts); } по public function index() { $posts = Post::where('verified', '1') ->orderBy('created_at','desc') ->groupBy('topic', 'publisher_id') ->paginate(5); // dd($posts); } 

Между тем данные в базе данных выглядят следующим образом:

 | id | verified | topic | publisher_id | body | created_at | | 25 | 1 | Forest | 3 | EE | 10.12.50 | | 24 | 1 | Forest | 3 | DD | 10.11.40 | | 23 | 1 | Forest | 3 | CC | 10.10.30 | | 22 | 1 | Dance | 2 | BB | 9.50.50 | | 21 | 1 | Dance | 2 | AA | 9.40.40 | | 20 | 1 | Music | 1 | ZZ | 9.30.30 | | 19 | 1 | Music | 1 | XX | 9.20.20 | | 18 | 1 | Art | 1 | YY | 9.10.10 | | 17 | 1 | Art | 1 | WW | 9.00.00 | | 16 | 1 | Ski | 2 | KK | 7.00.00 | 

Когда я раскомментирую dd() и запускаю код, я получаю этот журнал:

  LengthAwarePaginator { ... items : { items : { 0 => Post{..} 1 => Post{..} 2 => Post{..} 3 => Post{..} ... } } ... } 

0 => Post{#249} : "published_by: "3", "body": "CC", "created_at": "10.10.30"

1 => Post{#250} : "published_by: "1", "body": "XX", "created_at": "9.20.20"

2 => Post{#251} : "published_by: "1", "body": "WW", "created_at": "9.00.00"

3 => Post{#252} : "published_by: "2", "body": "KK", "created_at": "7.00.00"

Это выглядит странно по какой-то причине. Он сделал groupBy для пользователя-3, но не для других. Кроме того, он потянет самое раннее, созданное, а не последнее. Изменение desc to asc like ->orderBy('created_at', 'asc') полностью вывело бы из строя.

Другими словами, возвращая 'CC' for user-3, Forest вместо 'EE' for user-3, Forest

Тогда я подумал, что, возможно, это ->paginate(5) .

 public function post() { $posts = Post::where... ... ->paginate(5); $postsTry = Post::where('verified', '1') ->orderBy('created_at','desc') ->groupBy('topic', 'publisher_id') ->get(); // dd($postsTry); } по public function post() { $posts = Post::where... ... ->paginate(5); $postsTry = Post::where('verified', '1') ->orderBy('created_at','desc') ->groupBy('topic', 'publisher_id') ->get(); // dd($postsTry); } 

Я получаю коллекцию только с такими items как над ним. ( 0 => Post{..}, 1 => Post{..}, 2 => Post{..} ).

Он группирует данные как самые ранние сначала, а не последние сначала . Что мне не хватает? Что я делаю неправильно?


Чтобы завершить, обратите внимание, что я хочу получить:

'EE' for user-3, Forest

'BB' for user-2, Dance

'ZZ' for user-1, Music

'YY' for user-1, Art

Убрал мой предыдущий ответ, но все равно будет включать примечание от Laravel Pagination о groupBy() с помощью paginate() .

Примечание. В настоящее время операции с groupBy по groupBy которые используют оператор groupBy не могут эффективно выполняться Laravel. Если вам нужно использовать groupBy с groupBy на страницы набором результатов, рекомендуется запросить базу данных и создать файл-указатель вручную.

ОБНОВИТЬ

Из-за вашего необычного формата даты для поля created_at вам понадобятся целочисленные значения cast ed, которые будут использоваться правилом order by statement (как целое, а не строка). Вот рабочий пример:

 Post::selectRaw("*, CAST(REPLACE(created_at, '.', '') AS UNSIGNED INTEGER) ca") ->where('verified', '1') ->orderBy('ca', 'desc') ->groupBy('topic', 'publisher_id') ->paginate(); 

Вам нужно будет использовать подзапрос (или другой метод соединения), чтобы получить верхний элемент в вашей группе. См. Раздел « Получение строк», удерживающих групповой максимум определенного столбца

Удалил мой пример.