Skip to content

Commit de3894e

Browse files
committed
comparison filter
1 parent 9af65a2 commit de3894e

1 file changed

Lines changed: 158 additions & 0 deletions

File tree

core/doctrine-filters.md

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ To add some search filters, choose over this new list:
186186
- [PartialSearchFilter](#partial-search-filter) (filter using a `LIKE %value%`)
187187
- [FreeTextQueryFilter](#free-text-query-filter) (allows you to apply multiple filters to multiple properties of a resource at the same time, using a single parameter in the URL)
188188
- [OrFilter](#or-filter) (apply a filter using `orWhere` instead of `andWhere` )
189+
- [ComparisonFilter](#comparison-filter) (add `gt`, `gte`, `lt`, `lte`, `ne` operators to an equality or UUID filter)
189190

190191
### Legacy SearchFilter (API Platform < 4.2))
191192

@@ -491,6 +492,163 @@ This request will return all chickens where:
491492
- OR
492493
- the `ean` is exactly "FR123456".
493494

495+
## Comparison Filter
496+
497+
> [!NOTE]
498+
> `ComparisonFilter` is experimental and its API may change before a stable release.
499+
500+
The comparison filter is a decorator that wraps an equality filter (such as `ExactFilter`) and adds comparison
501+
operators to it. It lets clients filter a collection using greater-than, greater-than-or-equal, less-than,
502+
less-than-or-equal, and not-equal comparisons on any filterable property.
503+
504+
Syntax: `?parameter[<gt|gte|lt|lte|ne>]=value`
505+
506+
Available operators:
507+
508+
| Operator | SQL equivalent | Description |
509+
|---|---|---|
510+
| `gt` | `>` | Strictly greater than |
511+
| `gte` | `>=` | Greater than or equal to |
512+
| `lt` | `<` | Strictly less than |
513+
| `lte` | `<=` | Less than or equal to |
514+
| `ne` | `!=` | Not equal to |
515+
516+
`ComparisonFilter` is a decorator: it is applied by wrapping another filter. The canonical pairing is with `ExactFilter`
517+
for standard properties, or with `UuidFilter` for UUID columns.
518+
It works for Doctrine ORM (`ApiPlatform\Doctrine\Orm\Filter\ComparisonFilter`) and Doctrine MongoDB ODM
519+
(`ApiPlatform\Doctrine\Odm\Filter\ComparisonFilter`).
520+
521+
```php
522+
<?php
523+
// api/src/ApiResource/Product.php
524+
namespace App\ApiResource;
525+
526+
use ApiPlatform\Doctrine\Orm\Filter\ComparisonFilter;
527+
use ApiPlatform\Doctrine\Orm\Filter\ExactFilter;
528+
use ApiPlatform\Metadata\ApiResource;
529+
use ApiPlatform\Metadata\GetCollection;
530+
use ApiPlatform\Metadata\QueryParameter;
531+
532+
#[ApiResource]
533+
#[GetCollection(
534+
parameters: [
535+
'price' => new QueryParameter(
536+
filter: new ComparisonFilter(new ExactFilter()),
537+
property: 'price',
538+
),
539+
],
540+
)]
541+
class Product
542+
{
543+
// ...
544+
}
545+
```
546+
547+
Given that the collection endpoint is `/products`, you can filter products by price range with the following queries:
548+
549+
- `/products?price[gt]=10` — products whose price is strictly greater than 10
550+
- `/products?price[gte]=10` — products whose price is greater than or equal to 10
551+
- `/products?price[lt]=100` — products whose price is strictly less than 100
552+
- `/products?price[lte]=100` — products whose price is less than or equal to 100
553+
- `/products?price[ne]=0` — products whose price is not equal to 0
554+
555+
### Range Queries (Combining Operators)
556+
557+
There is no dedicated `between` operator. To filter within a range, combine `gte` and `lte` (or `gt` and `lt`) in a
558+
single request:
559+
560+
```
561+
GET /products?price[gte]=10&price[lte]=100
562+
```
563+
564+
This returns all products whose price is between 10 and 100 inclusive.
565+
566+
### DateTime Support
567+
568+
`ComparisonFilter` accepts `DateTimeInterface` values. When the underlying property is typed as a `DateTime` or
569+
`DateTimeImmutable`, API Platform automatically casts the raw string from the query string into a `DateTimeImmutable`
570+
before passing it to the filter. Any format accepted by the PHP
571+
[`DateTimeImmutable` constructor](https://www.php.net/manual/en/datetime.construct.php) is valid.
572+
573+
```php
574+
<?php
575+
// api/src/ApiResource/Event.php
576+
namespace App\ApiResource;
577+
578+
use ApiPlatform\Doctrine\Orm\Filter\ComparisonFilter;
579+
use ApiPlatform\Doctrine\Orm\Filter\ExactFilter;
580+
use ApiPlatform\Metadata\ApiResource;
581+
use ApiPlatform\Metadata\GetCollection;
582+
use ApiPlatform\Metadata\QueryParameter;
583+
584+
#[ApiResource]
585+
#[GetCollection(
586+
parameters: [
587+
'startDate' => new QueryParameter(
588+
filter: new ComparisonFilter(new ExactFilter()),
589+
property: 'startDate',
590+
),
591+
],
592+
)]
593+
class Event
594+
{
595+
// ...
596+
}
597+
```
598+
599+
Example request to fetch events starting after a given date:
600+
601+
```
602+
GET /events?startDate[gt]=2025-01-01T00:00:00Z
603+
```
604+
605+
### UUID Support
606+
607+
`ComparisonFilter` can also wrap `UuidFilter` to enable comparison operators on UUID columns. This is especially useful
608+
for cursor-based pagination on time-ordered UUIDs (UUID v7), where the lexicographic order of UUIDs matches their
609+
chronological order.
610+
611+
```php
612+
<?php
613+
// api/src/ApiResource/Device.php
614+
namespace App\ApiResource;
615+
616+
use ApiPlatform\Doctrine\Orm\Filter\ComparisonFilter;
617+
use ApiPlatform\Doctrine\Orm\Filter\UuidFilter;
618+
use ApiPlatform\Metadata\ApiResource;
619+
use ApiPlatform\Metadata\GetCollection;
620+
use ApiPlatform\Metadata\QueryParameter;
621+
622+
#[ApiResource]
623+
#[GetCollection(
624+
parameters: [
625+
'id' => new QueryParameter(
626+
filter: new ComparisonFilter(new UuidFilter()),
627+
property: 'id',
628+
),
629+
],
630+
)]
631+
class Device
632+
{
633+
// ...
634+
}
635+
```
636+
637+
Example requests:
638+
639+
- `/devices?id[gt]=0192d4e0-7b5a-7a3f-9e1c-4b8f2a1c3d5e` — devices created after the given UUID
640+
- `/devices?id[gte]=...&id[lte]=...` — devices within a UUID range
641+
- `/devices?id[ne]=...` — exclude a specific device
642+
643+
`UuidFilter` handles the conversion of UUID strings to their database binary representation via Doctrine's type system,
644+
which is required for correct comparisons on binary UUID columns.
645+
646+
### OpenAPI Documentation
647+
648+
`ComparisonFilter` automatically generates five OpenAPI query parameters for each configured parameter key, one per
649+
operator. For a parameter named `price`, the generated parameters are `price[gt]`, `price[gte]`, `price[lt]`,
650+
`price[lte]`, and `price[ne]`.
651+
494652
## Date Filter
495653

496654
The date filter allows filtering a collection by date intervals.

0 commit comments

Comments
 (0)