@@ -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\A piResource;
418+
419+ use ApiPlatform\D octrine\O rm\F ilter\C omparisonFilter;
420+ use ApiPlatform\D octrine\O rm\F ilter\E xactFilter;
421+ use ApiPlatform\M etadata\A piResource;
422+ use ApiPlatform\M etadata\G etCollection;
423+ use ApiPlatform\M etadata\Q ueryParameter;
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\A piResource;
470+
471+ use ApiPlatform\D octrine\O rm\F ilter\C omparisonFilter;
472+ use ApiPlatform\D octrine\O rm\F ilter\E xactFilter;
473+ use ApiPlatform\M etadata\A piResource;
474+ use ApiPlatform\M etadata\G etCollection;
475+ use ApiPlatform\M etadata\Q ueryParameter;
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\A piResource;
508+
509+ use ApiPlatform\D octrine\O rm\F ilter\C omparisonFilter;
510+ use ApiPlatform\D octrine\O rm\F ilter\UuidFilte r;
511+ use ApiPlatform\M etadata\A piResource;
512+ use ApiPlatform\M etadata\G etCollection;
513+ use ApiPlatform\M etadata\Q ueryParameter;
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
389547The date filter allows filtering a collection by date intervals.
0 commit comments