---
title: "Validating filter values — Query Builder for Laravel | Roundly"
description: "Wrap your validation rules in FilterValue so operator prefixes and sentinels are stripped before the rules run."
url: https://roundly-consulting.com/open-source/docs/query-builder-for-laravel/validation
language: en
---

[All packages](https://roundly-consulting.com/open-source.md)

[Query Builder for Laravel](https://roundly-consulting.com/open-source/docs/query-builder-for-laravel.md)

# Validating filter values

A list endpoint usually validates what a filter may contain — Rule::in(), integer, uuid — so a typo is a helpful 422 instead of a silently empty list. Once a filter accepts operators, those rules start rejecting the wire: gte:500 is not an integer and not:debug is not a valid level. The FilterValue rule strips the operator prefix and sentinels, then runs your original rules against what remains:

```php
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
use RoundlyConsulting\QueryBuilder\Concerns\HasPageSize;
use RoundlyConsulting\QueryBuilder\Enums\RequestedOperator;
use RoundlyConsulting\QueryBuilder\Rules\FilterValue;
use RoundlyConsulting\QueryBuilder\Support\FilterSentinel;

final class ListLogsRequest extends FormRequest
{
    use HasPageSize;

    public function rules(): array
    {
        return [
            ...$this->pageSizeRules(),
            'filter.level' => ['nullable', new FilterValue(Rule::enum(LogLevel::class))],
            'filter.code' => ['nullable', new FilterValue('integer', operators: [
                RequestedOperator::GreaterThanOrEqual,
                RequestedOperator::LessThan,
            ])],
            'filter.project' => ['nullable', new FilterValue('uuid', sentinels: [FilterSentinel::NONE])],
        ];
    }
}

// ?filter[level]=not:debug  → passes (debug is a LogLevel case)
// ?filter[code]=gte:500     → passes
// ?filter[code]=gte:garbage → 422 with the endpoint's own "integer" message
// ?filter[project]=none     → passes (the sentinel is skipped)
```

The matching filters in the controller:

```php
->allowedFilters(
    AllowedFilter::operators('level', [RequestedOperator::Not]),
    AllowedFilter::operators('code', [RequestedOperator::GreaterThanOrEqual, RequestedOperator::LessThan]),
    AllowedFilter::nullable('project', 'project_id', FilterValueShape::Uuid),
)
```

## Rule options

new FilterValue($rules, ?array $operators = null, array $sentinels = \[\], bool $partialByDefault = false):

- $rules — the rules a bare value would get: a rule string, a list, or a rule object. The endpoint keeps its own messages and attribute names.
- operators — the tokens the filter declared. Defaults to the equality pair (is, not); a comparison or partial filter has to say so.
- sentinels — reserved values the filter answers itself, such as FilterSentinel::NONE, which the column rules would otherwise reject.
- partialByDefault — mirror the filter’s flag; it decides which operator a bare value means, and that one is always stripped.

Pass the same operators and sentinel the filter declared — the two halves are one declaration. Every item of a comma/array value is validated (a multi-select sends several), capped by limits.max\_filter\_values.

## Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

[More ways to support, including crypto](https://roundly-consulting.com/support-us.md)

By donating, you agree to our [donation terms](https://roundly-consulting.com/donation-terms.md).

[Support our open source work (opens in a new tab)](https://donate.stripe.com/dRmeVe8FX5PF1Qd9pXcEw00) [Join us on Patreon (opens in a new tab)](https://www.patreon.com/cw/roundly)

## Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.

[Get a quote in 48 hours](https://roundly-consulting.com/contact.md) [Browse all packages](https://roundly-consulting.com/open-source/docs/query-builder-for-laravel.md)
