Как упорядочить результаты запросов в Eloquent
Development | Комментировать запись
Eloquent – это объектно-реляционный преобразователь (ORM), который включен в структуру Laravel по умолчанию. В этой серии статей вы узнаете, как делать запросы к базе данных и как работать с отношениями в Laravel Eloquent. Также вы сможете попрактиковаться на примерах: мы попробуем улучшить демо-приложение с помощью новых моделей и отношений.
Примечание: Все мануалы данной серии можно найти по тегу Laravel Eloquent.
В предыдущей части этой серии вы узнали, как извлечь записи БД с помощью метода all() в модели Eloquent. Вспомните, как мы использовали метод sortDesc() для сортировки записей в порядке убывания.
Метод sortDesc() является частью класса Collection – мощного служебного класса Laravel, который работает как улучшенная версия массивов PHP. Вместо того чтобы упорядочивать результаты в самом запросе к БД, этот метод инвертирует порядок коллекции (то есть последний элемент появляется первым в коллекции). Такой подход хорошо работает в небольших наборах результатов, однако не поддерживает сортировку результатов в самом запросе к базе данных (а значит, не обеспечивает достаточного уровня гибкости).
Чтобы отсортировать результаты в запросе к БД, нужно использовать метод orderBy() и указать поле таблицы, которое вы хотите использовать в качестве критерия для упорядочивания. Такой подход дает больше гибкости при построении запроса, и в итоге он сможет извлекать из БД только те результаты, которые вам нужны.
Давайте изменим код в файле routes/web.php, чтобы отобразить результаты, упорядоченные на основе поля таблицы created_at (от самых новых к самым старым).
Примечание: Eloquent управляет полями created_at и updated_at, если вы включаете определение timestamps() в миграцию таблицы. Вы не должны обновлять эти поля вручную, но можете использовать их для сортировки и фильтрации запросов.
Откройте файл в редакторе кода:
routes/web.php
Вот как он выглядит сейчас:
<?php
use Illuminate\Support\Facades\Route;
use App\Models\Link;
use App\Models\LinkList;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::get('/', function () {
$links = Link::all()->sortDesc();
return view('index', [
'links' => $links,
'lists' => LinkList::all()
]);
});
Route::get('/{slug}', function ($slug) {
$list = LinkList::where('slug', $slug)->first();
if (!$list) {
abort(404);
}
return view('index', [
'list' => $list,
'links' => $list->links,
'lists' => LinkList::all()
]);
})->name('link-list');
Обратите внимание, маршрут /{slug}, отвечающий за формирование списка ссылок по слагам, в настоящее время не использует никаких методов сортировки. Ссылки извлекаются через переменную list при помощи отношения, определенного в модели LinkList.
Если сейчас вы добавите в список несколько ссылок, запрос по умолчанию выведет результаты, упорядоченные от старых к новым. Для изменения порядка коллекции в вызове $list->links вы можете использовать метод sortDesc(), однако метод orderBy() обеспечивает большую гибкость и в дальнейшем позволяет включать дополнительные условия фильтрации. Вы можете связать этот метод с вызовом where() для получения еще более подробных результатов.
Замените выделенную строку в предыдущем примере кода следующей строкой:
'links' => $list->links()->orderBy('created_at', 'desc')->get(),
Обратите внимание, на этот раз мы вызываем встроенный сборщик запросов через метод $list->links(), который относится к методу отношений (их мы определили в классе LinkList). Это не то же самое, что вызвать $ list->links в качестве свойства класса (без скобок) – это вызывает в модели метод для выборки всех ссылок, связанных с заданным списком.
Вот как должен выглядеть готовый файл routes/web.php, когда вы закончите его редактировать:
<?php use Illuminate\Support\Facades\Route; use App\Models\Link; use App\Models\LinkList; /* |-------------------------------------------------------------------------- | Web Routes |-------------------------------------------------------------------------- | | Here is where you can register web routes for your application. These | routes are loaded by the RouteServiceProvider within a group which | contains the "web" middleware group. Now create something great! | */ Route::get('/', function () { $links = Link::all()->sortDesc(); return view('index', [ 'links' => $links, 'lists' => LinkList::all() ]); }); Route::get('/{slug}', function ($slug) { $list = LinkList::where('slug', $slug)->first(); if (!$list) { abort(404); } return view('index', [ 'list' => $list, 'links' => $list->links()->orderBy('created_at', 'desc')->get(), 'lists' => LinkList::all() ]); })->name('link-list');
Сохраните и закройте файл. Теперь добавьте пару новых ссылок, используя Artisan-команду link:new. Вы можете использовать стандартный список:
docker-compose exec app php artisan link:new
Команда вернет такой результат:
Link URL: > https://laravel.com/docs/8.x/eloquent Link Description: > Laravel Eloquent Docs Link List (leave blank to use default): > New Link: https://laravel.com/docs/8.x/eloquent - Laravel Eloquent Docs Listed in: default Is this information correct? (yes/no) [no]: > yes Saved.
Если вы перезагрузите страницу с вашим списком ссылок, вы увидите, что теперь ссылки упорядочены от самых новых до самых старых.
Аналогичным образом можно упорядочить ссылки в алфавитном порядке (по описанию ссылки): для этого вам придется изменить строку в файле routes/web.php, чтобы использовать другое поле таблицы в вызове метода. Эта строка должна выглядеть следующим образом:
'links' => $list->links()->orderBy('description', 'asc')->get(),
Если вы обновите страницу после такого изменения, вы увидите, что теперь ссылки упорядочены в алфавитном порядке.
В следующем мануале этой серии вы узнаете, как узнать общее количество извлеченных результатов с помощью запроса Laravel Eloquent.
Tags: Eloquent, Laravel, Laravel Eloquent, ORM