Сортировки
sorts() перечисляет сортировки, которые может использовать запрос клиента. sort=name,-created_at сортирует по перечисленным именам, - — по убыванию:
public function sorts(): array
{
return [
'name',
Sort::field('created')->column('created_at'),
Sort::relation('profile.country.name')->as('country'),
Sort::count('posts'),
Sort::max('posts', 'views')->clientNulls(),
Sort::callback('popularity', fn ($query, bool $descending) => ...),
];
}
public function defaultSorts(): array
{
return ['-created'];
}defaultSorts() применяется, когда в запросе клиента нет sort.
Виды
- Строка или
Sort::field('created')->column('created_at'): колонка модели. Sort::callback('popularity', fn ($query, bool $descending) => ...).Sort::relation('profile.country.name'): колонка связанной модели по связи «к одному», через любую цепочку связей «к одному». Запрашивается по пути, если не переименована через->as('country'). Строки без связанной модели сортируются какNULL. Путь черезmorphToпринимает->morphTypes(...), как фильтр.Sort::count('posts'),exists,min,max,sum,avg: агрегат связи, названный как агрегатныйinclude(postsCount,postsMaxViews), без подгрузки связи.
Значения NULL
->nullsFirst() / ->nullsLast() ставят значения NULL первыми или последними при любом направлении.
Без них агрегатная сортировка (min, max, sum, avg: NULL у родителя без связанных строк) считает NULL наименьшим значением на любой БД, как MySQL и SQLite: первым по возрастанию, последним по убыванию. На PostgreSQL пакет добавляет нужный порядок сам.
->clientNulls() позволяет запросу клиента выбрать, куда идут значения NULL (для любой сортировки, кроме callback). Клиент добавляет :nulls-first или :nulls-last после имени, в sort и в sort_included:
Sort::field('nickname')->nullsLast()->clientNulls(),
Sort::max('posts', 'views')->clientNulls(),GET /users?sort=-postsMaxViews:nulls-last,nickname:nulls-firstnullsFirst()/nullsLast() остаются умолчанием, когда запрос клиента не передаёт суффикс (sort=nickname выше оставляет значения NULL последними), а суффикс их переопределяет. Суффикс на сортировке без clientNulls() отклоняется с nulls_not_allowed, неизвестный (:nulls-middle) — с invalid_value. Сортировки по умолчанию суффикс не принимают: объявите сортировку с nullsFirst()/nullsLast().
Сортировки вложенных определений
Relationship::to('posts', PostQuery::class)->withSorts() публикует сортировки PostQuery. Они решают две разные задачи, у каждой свой параметр:
GET /users?include=posts,latestPost&sort=-latestPost.views&sort_included[posts]=-views,titlesortвсегда упорядочивает основной список. Через связь «к одному» (latestPost,author,profile) сортировки по полям и связям вложенного определения доступны как<path>.<name>:sort=-latestPost.viewsупорядочивает пользователей по просмотрам их последнего поста. У связи «ко многим» нет одной строки, по которой сортировать, поэтомуsort=posts.viewsотклоняется с подсказкой: сортируйте по агрегату (Sort::max('posts', 'views')).sort_included[<include path>]упорядочивает подгруженные строки:sort_included[posts]=-viewsвыводит посты каждого пользователя по просмотрам. Доступна любая сортировка вложенного определения, включая агрегаты и callback, и вложенные пути тоже работают (sort_included[posts.comments]=-created_at). Путь должен быть подгружен (или быть префиксом подгрузки), иначе запрос клиента отклоняется сunknown_include.
Вложенные определения, помеченные так же, публикуют свои сортировки под полным путём, если помечена каждая связь на этом пути. Сортировки по умолчанию вложенного определения к подгруженным строкам не применяются.