Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Як спроєктувати фільтрацію, сортування й вибір полів у REST API?

Списки в API майже завжди потребують фільтрів, сортування й обмеження полів. Головне - однакова схема для всіх ендпойнтів, щоб клієнтам не доводилося вчити кожен окремо.

Поширена схема (близька до JSON:API):

GET /api/vacancies?filter[city]=kyiv&filter[remote]=1&filter[salary_from]=2000
    &sort=-published_at,title
    &fields[vacancies]=id,title,salary
    &include=company
    &page[size]=20
  • filter[...] - умови; для діапазонів - суфікси (salary_from/salary_to) або оператори (filter[salary][gte]=2000);
  • sort - список полів через кому, - - за спаданням;
  • fields[тип] - лише потрібні поля (sparse fieldsets): мобільному списку не треба повного опису вакансії;
  • include - пов'язані ресурси в тій самій відповіді.

У Laravel розбір таких параметрів дає spatie/laravel-query-builder:

QueryBuilder::for(Vacancy::class)
    ->allowedFilters(['city', AllowedFilter::exact('remote'), AllowedFilter::scope('salary_from')])
    ->allowedSorts(['published_at', 'title'])
    ->allowedFields(['id', 'title', 'salary'])
    ->allowedIncludes(['company'])
    ->paginate();

А вбудовані JSON:API-ресурси Laravel (JsonApiResource) самі обробляють fields і include у відповіді.

Безпека й продуктивність - головне:

  • білий список полів для фільтрів, сортування й include. Сортування за довільною колонкою з параметра - це і SQL-ризики, і повільні запити за полями без індексу. Невідомий параметр - помилка 400, а не тихе ігнорування;
  • індекси під реальні фільтри: кожна дозволена комбінація фільтр + сортування - потенційний запит, і для частих комбінацій потрібні складені індекси;
  • обмеження глибини include і кількості елементів - інакше один запит витягне половину бази;
  • приховані поля: fields не повинен відкривати поля, яких немає в звичайній відповіді (password_hash, внутрішні примітки).

Пошук за текстом - окремий параметр (filter[q]=laravel чи q=), який веде в повнотекстовий пошук (Scout, Meilisearch), а не в LIKE '%...%' по кількох колонках.

Документування: кожен дозволений фільтр і сортування мають бути в OpenAPI-описі - інакше клієнти вгадують.

Докладніше в документації: JSON:API: sparse fieldsets

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

Схожі питання