У меня есть таблица «сообщений» со следующими столбцами
CREATE TABLE `messages` ( `id` int(11) NOT NULL AUTO_INCREMENT, `fromId` int(11) NOT NULL, `toId` int(11) NOT NULL, `message` text NOT NULL, `status` int(11) NOT NULL, `device` varchar(100) NOT NULL, `createdAt` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=57 DEFAULT CHARSET=latin1;
Я пытаюсь получить все сообщения, где «toId» = $ id и группировка byId. Проблема в том, что «сообщение», показанное на результатах, является первым, а не последним. Я попробовал упорядочить по createdAt, но он не работает.
Как я могу заказать «createdAt» до запроса и группировки результатов? Я хочу сделать это по-ларавийски, используя Eloquent.
Мой запрос:
$chats = Message::with('sender','recipient') ->where('toId',$id) ->orderBy('createdAt') ->groupBy('fromId') ->paginate(10)
Мне просто нужно было сделать что-то подобное с моделью сообщений. То, что сработало для меня, было применение unique
метода в возвращенной красноречивой коллекции.
Model::where('toId', $id) ->orderBy('createdAt', 'desc') ->get() ->unique('fromId');
Запрос вернет все сообщения, упорядоченные с помощью createdAt
и unique
метод уменьшит его до одного сообщения для каждого fromId
. Это, очевидно, не так сильно, как использование базы данных напрямую, но в моем случае у меня есть дополнительные ограничения на запрос.
Кроме того, есть много полезных методов для работы с этими коллекциями: https://laravel.com/docs/5.2/collections#available-methods
Эта работа для меня: (вы можете удалить заказ by createdAt в случае, если createAt увеличивается вместе с id)
DB::select(DB::raw('select * from (select * from messages group by fromId desc) m order by m.createdAt'));
Это должно быть что-то вроде этого:
Message::whereToId($id)->groupBy('fromId')->latest('createdAt')->first();
Обновить
После просмотра запроса, который вы добавили, вам просто нужно добавить направление к функции orderBy
, например:
$chats = Message::with('sender','recipient') ->select(DB::raw('*, max(createdAt) as createdAt')) ->where('toId',$id) ->orderBy('createdAt', 'desc') ->groupBy('fromId') ->paginate(10)
Я нашел способ сделать это! В принципе, создаем подзапрос и запускаем его раньше, чтобы результаты упорядочивались как ожидалось и сгруппировались после.
Вот код:
$sub = Message::orderBy('createdAt','DESC'); $chats = DB::table(DB::raw("({$sub->toSql()}) as sub")) ->where('toId',$id) ->groupBy('fromId') ->get();