Фильтрация
allowedFilters() перечисляет фильтры, которые может использовать запрос клиента. Фильтры передаются как filter[<name>]=<value>:
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 клиент ставит оператор в начало значения:
use MyProgs\QueryBuilder\Enums\FilterOperator;
AllowedFilter::operator('salary', FilterOperator::DYNAMIC)GET /users?filter[salary]=>=3000Операторы: =, <>, <, >, <= и >=. Значение без оператора сравнивается через =. Третий аргумент, 'or', объединяет сравнение через or вместо and.
Scope
AllowedFilter::scope('active') вызывает локальный скоуп модели со значением в качестве аргумента; список передаётся как несколько аргументов:
public function scopeCreatedBetween(Builder $query, $from, $to): void
{
$query->whereBetween('created_at', [$from, $to]);
}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
AllowedFilter::callback('has_posts', function (Builder $query, mixed $value, string $property) {
$query->whereHas('posts');
})Собственные классы фильтров
Реализуйте MyProgs\QueryBuilder\Filters\Filter и зарегистрируйте его через custom():
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));
}
}AllowedFilter::custom('permission', new FiltersUserPermission)Группы
AllowedFilter::groupOr() применяет одно значение к нескольким фильтрам, объединённым через or, внутри одного where в скобках; groupAnd() объединяет их через and:
AllowedFilter::groupOr('search', [
AllowedFilter::partial('name'),
AllowedFilter::partial('email'),
])GET /users?filter[search]=johnФильтрация через связи
Имя через точку фильтрует через связь с помощью whereHas():
AllowedFilter::exact('posts.status')GET /users?filter[posts.status]=publishedПередайте false третьим аргументом exact, partial, beginsWith, endsWith или operator, чтобы точка считалась частью имени колонки (AllowedFilter::exact('meta.type', null, false)).
Параметры
Другое имя колонки
Второй аргумент — колонка или скоуп, стоящие за именем, которое использует клиент:
AllowedFilter::exact('author', 'user_id')Значения по умолчанию
AllowedFilter::exact('status')->default('published')Значение по умолчанию используется, когда запрос клиента не упоминает фильтр. unsetDefault() убирает его.
Фильтры, допускающие NULL
AllowedFilter::exact('deleted_at')->nullable()Тогда пустое значение (filter[deleted_at]=) совпадает с NULL, а не игнорируется. Значение по умолчанию null тоже делает фильтр nullable.
Игнорируемые значения
AllowedFilter::exact('status')->ignore('all', null)Перечисленные значения отбрасываются из значения запроса; фильтр, у которого ничего не осталось, не применяется.
Разделитель
AllowedFilter::exact('name')->delimiter('|')Разделитель только этого фильтра: filter[name]=Smith, John|Doe, Jane. По умолчанию он берётся из ключа конфигурации delimiter.