Skip to content

Commit fd30c4c

Browse files
committed
comparison filter
1 parent b542fbd commit fd30c4c

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
@@ -134,6 +134,7 @@ To add some search filters, choose over this new list:
134134
- [FreeTextQueryFilter](#free-text-query-filter) (allows you to apply multiple filters to multiple
135135
properties of a resource at the same time, using a single parameter in the URL)
136136
- [OrFilter](#or-filter) (apply a filter using `orWhere` instead of `andWhere` )
137+
- [ComparisonFilter](#comparison-filter) (add `gt`, `gte`, `lt`, `lte`, `ne` operators to an equality or UUID filter)
137138

138139
### SearchFilter
139140

@@ -384,6 +385,163 @@ This request will return all chickens where:
384385
- OR
385386
- the `ean` is exactly "FR123456".
386387

388+
## Comparison Filter
389+
390+
> [!NOTE]
391+
> `ComparisonFilter` is experimental and its API may change before a stable release.
392+
393+
The comparison filter is a decorator that wraps an equality filter (such as `ExactFilter`) and adds comparison
394+
operators to it. It lets clients filter a collection using greater-than, greater-than-or-equal, less-than,
395+
less-than-or-equal, and not-equal comparisons on any filterable property.
396+
397+
Syntax: `?parameter[<gt|gte|lt|lte|ne>]=value`
398+
399+
Available operators:
400+
401+
| Operator | SQL equivalent | Description |
402+
| --- | --- | --- |
403+
| `gt` | `>` | Strictly greater than |
404+
| `gte` | `>=` | Greater than or equal to |
405+
| `lt` | `<` | Strictly less than |
406+
| `lte` | `<=` | Less than or equal to |
407+
| `ne` | `!=` | Not equal to |
408+
409+
`ComparisonFilter` is a decorator: it is applied by wrapping another filter. The canonical pairing is with `ExactFilter`
410+
for standard properties, or with `UuidFilter` for UUID columns.
411+
It works for Doctrine ORM (`ApiPlatform\Doctrine\Orm\Filter\ComparisonFilter`) and Doctrine MongoDB ODM
412+
(`ApiPlatform\Doctrine\Odm\Filter\ComparisonFilter`).
413+
414+
```php
415+
<?php
416+
// api/src/ApiResource/Product.php
417+
namespace App\ApiResource;
418+
419+
use ApiPlatform\Doctrine\Orm\Filter\ComparisonFilter;
420+
use ApiPlatform\Doctrine\Orm\Filter\ExactFilter;
421+
use ApiPlatform\Metadata\ApiResource;
422+
use ApiPlatform\Metadata\GetCollection;
423+
use ApiPlatform\Metadata\QueryParameter;
424+
425+
#[ApiResource]
426+
#[GetCollection(
427+
parameters: [
428+
'price' => new QueryParameter(
429+
filter: new ComparisonFilter(new ExactFilter()),
430+
property: 'price',
431+
),
432+
],
433+
)]
434+
class Product
435+
{
436+
// ...
437+
}
438+
```
439+
440+
Given that the collection endpoint is `/products`, you can filter products by price range with the following queries:
441+
442+
- `/products?price[gt]=10` — products whose price is strictly greater than 10
443+
- `/products?price[gte]=10` — products whose price is greater than or equal to 10
444+
- `/products?price[lt]=100` — products whose price is strictly less than 100
445+
- `/products?price[lte]=100` — products whose price is less than or equal to 100
446+
- `/products?price[ne]=0` — products whose price is not equal to 0
447+
448+
### Range Queries (Combining Operators)
449+
450+
There is no dedicated `between` operator. To filter within a range, combine `gte` and `lte` (or `gt` and `lt`) in a
451+
single request:
452+
453+
```http
454+
GET /products?price[gte]=10&price[lte]=100
455+
```
456+
457+
This returns all products whose price is between 10 and 100 inclusive.
458+
459+
### DateTime Support
460+
461+
`ComparisonFilter` accepts `DateTimeInterface` values. When the underlying property is typed as a `DateTime` or
462+
`DateTimeImmutable`, API Platform automatically casts the raw string from the query string into a `DateTimeImmutable`
463+
before passing it to the filter. Any format accepted by the PHP
464+
[`DateTimeImmutable` constructor](https://www.php.net/manual/en/datetime.construct.php) is valid.
465+
466+
```php
467+
<?php
468+
// api/src/ApiResource/Event.php
469+
namespace App\ApiResource;
470+
471+
use ApiPlatform\Doctrine\Orm\Filter\ComparisonFilter;
472+
use ApiPlatform\Doctrine\Orm\Filter\ExactFilter;
473+
use ApiPlatform\Metadata\ApiResource;
474+
use ApiPlatform\Metadata\GetCollection;
475+
use ApiPlatform\Metadata\QueryParameter;
476+
477+
#[ApiResource]
478+
#[GetCollection(
479+
parameters: [
480+
'startDate' => new QueryParameter(
481+
filter: new ComparisonFilter(new ExactFilter()),
482+
property: 'startDate',
483+
),
484+
],
485+
)]
486+
class Event
487+
{
488+
// ...
489+
}
490+
```
491+
492+
Example request to fetch events starting after a given date:
493+
494+
```http
495+
GET /events?startDate[gt]=2025-01-01T00:00:00Z
496+
```
497+
498+
### UUID Support
499+
500+
`ComparisonFilter` can also wrap `UuidFilter` to enable comparison operators on UUID columns. This is especially useful
501+
for cursor-based pagination on time-ordered UUIDs (UUID v7), where the lexicographic order of UUIDs matches their
502+
chronological order.
503+
504+
```php
505+
<?php
506+
// api/src/ApiResource/Device.php
507+
namespace App\ApiResource;
508+
509+
use ApiPlatform\Doctrine\Orm\Filter\ComparisonFilter;
510+
use ApiPlatform\Doctrine\Orm\Filter\UuidFilter;
511+
use ApiPlatform\Metadata\ApiResource;
512+
use ApiPlatform\Metadata\GetCollection;
513+
use ApiPlatform\Metadata\QueryParameter;
514+
515+
#[ApiResource]
516+
#[GetCollection(
517+
parameters: [
518+
'id' => new QueryParameter(
519+
filter: new ComparisonFilter(new UuidFilter()),
520+
property: 'id',
521+
),
522+
],
523+
)]
524+
class Device
525+
{
526+
// ...
527+
}
528+
```
529+
530+
Example requests:
531+
532+
- `/devices?id[gt]=0192d4e0-7b5a-7a3f-9e1c-4b8f2a1c3d5e` — devices created after the given UUID
533+
- `/devices?id[gte]=...&id[lte]=...` — devices within a UUID range
534+
- `/devices?id[ne]=...` — exclude a specific device
535+
536+
`UuidFilter` handles the conversion of UUID strings to their database binary representation via Doctrine's type system,
537+
which is required for correct comparisons on binary UUID columns.
538+
539+
### OpenAPI Documentation
540+
541+
`ComparisonFilter` automatically generates five OpenAPI query parameters for each configured parameter key, one per
542+
operator. For a parameter named `price`, the generated parameters are `price[gt]`, `price[gte]`, `price[lt]`,
543+
`price[lte]`, and `price[ne]`.
544+
387545
## Date Filter
388546

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

0 commit comments

Comments
 (0)