Skip to content

Сортировки ​

sorts() перечисляет сортировки, которые может использовать запрос клиента. sort=name,-created_at сортирует по перечисленным именам, - — по убыванию:

php
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:

php
Sort::field('nickname')->nullsLast()->clientNulls(),
Sort::max('posts', 'views')->clientNulls(),
GET /users?sort=-postsMaxViews:nulls-last,nickname:nulls-first

nullsFirst()/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,title
  • sort всегда упорядочивает основной список. Через связь «к одному» (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.

Вложенные определения, помеченные так же, публикуют свои сортировки под полным путём, если помечена каждая связь на этом пути. Сортировки по умолчанию вложенного определения к подгруженным строкам не применяются.