Skip to content

Фильтрация ​

allowedFilters() перечисляет фильтры, которые может использовать запрос клиента. Фильтры передаются как filter[<name>]=<value>:

php
QueryBuilder::for(User::class)
    ->allowedFilters('name', AllowedFilter::exact('id'))
    ->get();
GET /users?filter[name]=john&filter[id]=1,2,3

Фильтр не из списка выбрасывает InvalidFilterQuery.

Значения ​

  • Значение с разделителем — это список: filter[id]=1,2,3 даёт [1, 2, 3].
  • true и false становятся булевыми значениями.
  • Пустое значение (filter[name]=) игнорируется, если только фильтр не допускает NULL.

Типы фильтров ​

Частичное совпадение ​

Строка или AllowedFilter::partial('name'). Срабатывает, когда колонка содержит значение, без учёта регистра: LOWER(name) LIKE '%john%'. Список совпадает с любым из своих значений.

AllowedFilter::beginsWith('name') и AllowedFilter::endsWith('name') сравнивают начало или конец колонки.

Точное совпадение ​

AllowedFilter::exact('id') сравнивает через =, а список — через in. Подходит для id, статусов и булевых значений:

GET /users?filter[id]=1,2&filter[admin]=true

Оператор ​

AllowedFilter::operator('salary', FilterOperator::GREATER_THAN) сравнивает с фиксированным оператором. С FilterOperator::DYNAMIC клиент ставит оператор в начало значения:

php
use MyProgs\QueryBuilder\Enums\FilterOperator;

AllowedFilter::operator('salary', FilterOperator::DYNAMIC)
GET /users?filter[salary]=>=3000

Операторы: =, <>, <, >, <= и >=. Значение без оператора сравнивается через =. Третий аргумент, 'or', объединяет сравнение через or вместо and.

Scope ​

AllowedFilter::scope('active') вызывает локальный скоуп модели со значением в качестве аргумента; список передаётся как несколько аргументов:

php
public function scopeCreatedBetween(Builder $query, $from, $to): void
{
    $query->whereBetween('created_at', [$from, $to]);
}
php
AllowedFilter::scope('created_between')
GET /users?filter[created_between]=2026-01-01,2026-01-31

Чтобы найти скоуп, имя фильтра переводится в camel case. Параметр скоупа с типом модели получает модель, найденную через route binding, а неизвестный ключ выбрасывает InvalidFilterValue.

Belongs to ​

AllowedFilter::belongsTo('author') фильтрует по ключу связи belongsTo через whereBelongsTo(): filter[author]=1,2. Имя через точку фильтрует через связи: AllowedFilter::belongsTo('post.author').

Удалённые записи ​

AllowedFilter::trashed() для моделей с SoftDeletes: filter[trashed]=with включает удалённые модели, filter[trashed]=only возвращает только их, любое другое значение их исключает.

Callback ​

php
AllowedFilter::callback('has_posts', function (Builder $query, mixed $value, string $property) {
    $query->whereHas('posts');
})

Собственные классы фильтров ​

Реализуйте MyProgs\QueryBuilder\Filters\Filter и зарегистрируйте его через custom():

php
use Illuminate\Database\Eloquent\Builder;
use MyProgs\QueryBuilder\Filters\Filter;

class FiltersUserPermission implements Filter
{
    public function __invoke(Builder $query, mixed $value, string $property): void
    {
        $query->whereHas('permissions', fn (Builder $query) => $query->where('name', $value));
    }
}
php
AllowedFilter::custom('permission', new FiltersUserPermission)

Группы ​

AllowedFilter::groupOr() применяет одно значение к нескольким фильтрам, объединённым через or, внутри одного where в скобках; groupAnd() объединяет их через and:

php
AllowedFilter::groupOr('search', [
    AllowedFilter::partial('name'),
    AllowedFilter::partial('email'),
])
GET /users?filter[search]=john

Фильтрация через связи ​

Имя через точку фильтрует через связь с помощью whereHas():

php
AllowedFilter::exact('posts.status')
GET /users?filter[posts.status]=published

Передайте false третьим аргументом exact, partial, beginsWith, endsWith или operator, чтобы точка считалась частью имени колонки (AllowedFilter::exact('meta.type', null, false)).

Параметры ​

Другое имя колонки ​

Второй аргумент — колонка или скоуп, стоящие за именем, которое использует клиент:

php
AllowedFilter::exact('author', 'user_id')

Значения по умолчанию ​

php
AllowedFilter::exact('status')->default('published')

Значение по умолчанию используется, когда запрос клиента не упоминает фильтр. unsetDefault() убирает его.

Фильтры, допускающие NULL ​

php
AllowedFilter::exact('deleted_at')->nullable()

Тогда пустое значение (filter[deleted_at]=) совпадает с NULL, а не игнорируется. Значение по умолчанию null тоже делает фильтр nullable.

Игнорируемые значения ​

php
AllowedFilter::exact('status')->ignore('all', null)

Перечисленные значения отбрасываются из значения запроса; фильтр, у которого ничего не осталось, не применяется.

Разделитель ​

php
AllowedFilter::exact('name')->delimiter('|')

Разделитель только этого фильтра: filter[name]=Smith, John|Doe, Jane. По умолчанию он берётся из ключа конфигурации delimiter.