diff --git a/core/operations.md b/core/operations.md index 6239007ca39..780114e47f4 100644 --- a/core/operations.md +++ b/core/operations.md @@ -48,6 +48,167 @@ Item operations: | `PATCH` | no | Apply a partial modification to an element | yes | | `DELETE` | no | Delete an element | yes | +## The HTTP QUERY Operation + +[HTTP QUERY](https://www.rfc-editor.org/rfc/rfc10008.html) is a safe, idempotent collection +operation whose criteria are sent in the request body instead of the URI. It is useful when a +collection query is too large or too structured for a URL. API Platform does not enable it by +default; add a `Query` operation explicitly. + +Unlike `GET`, a `QUERY` request must include a `Content-Type` header, including when its body is +empty. API Platform supports `application/json` and `application/x-www-form-urlencoded` request +bodies for this operation. + +The following operation uses a parameter-driven filter. Although it is declared with +`QueryParameter`, the `name` criterion is sent in the `QUERY` request body, not as `?name=...` in +the URL: + +```php + new QueryParameter( + filter: new PartialSearchFilter(), + property: 'name', + ), + ]), +])] +class Book +{ + // ... +} +``` + +Call the `QUERY` operation with the same collection URI: + +```console +curl -X QUERY https://example.com/books \ + -H 'Accept: application/ld+json' \ + -H 'Content-Type: application/json' \ + --data '{"name":"Dune"}' +``` + +The parsed values are processed by the same [parameter and filter system](filters.md) as URL query +parameters. This lets existing `QueryParameter` filters describe and apply body criteria without a +custom provider. + +### Criteria DTOs + +For a structured query, set an `input` class on the operation and put `QueryParameter` attributes on +its properties. API Platform uses that class as the request-body schema and discovers its parameters +to apply their filters: + +```php +> */ +final readonly class BookCriteriaProcessor implements ProcessorInterface +{ + public function __construct(private BookSearch $bookSearch) {} + + public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): iterable + { + if (!$data instanceof BookCriteria) { + throw new \RutimeException('Expected BookCriteria.'); + } + + return $this->bookSearch->search($data); + } +} +``` + +This is the processor path: a processor is only called for a safe operation when `write` is set to +`true`. See [State Processors](state-processors.md) for implementing the processor. + +### OpenAPI + +When exporting an OpenAPI 3.2 document, API Platform represents the operation in the Path Item +Object's `query` field. Its request body lists `application/json` and +`application/x-www-form-urlencoded`; parameter-driven criteria are represented as body properties. +For an `input` criteria class, the request body references that class's input schema. Path and +header parameters remain OpenAPI parameters. + > [!NOTE] The `PATCH` method must be enabled explicitly in the configuration, refer to the > [Content Negotiation](content-negotiation.md) section for more information.