From fbf8a02620d28eebada445dc94e11f34db7f6a9c Mon Sep 17 00:00:00 2001 From: Takashi Kanemoto Date: Mon, 22 Sep 2025 13:28:34 +0900 Subject: [PATCH 1/2] docs(core/operations): update explanation about omitting GET item operation --- core/operations.md | 121 ++++++++++++++++++++++++------------------- symfony/messenger.md | 10 +--- 2 files changed, 68 insertions(+), 63 deletions(-) diff --git a/core/operations.md b/core/operations.md index 529fed04190..86f57c331c4 100644 --- a/core/operations.md +++ b/core/operations.md @@ -189,7 +189,18 @@ resources: API Platform is smart enough to automatically register the applicable Symfony route referencing a built-in CRUD action just by specifying the method name as key, or by checking the explicitly configured HTTP method. -If you do not want to allow access to the resource item (i.e. you don't want a `GET` item operation), instead of omitting it altogether, you should instead declare a `GET` item operation which returns HTTP 404 (Not Found), so that the resource item can still be identified by an IRI. For example: +By default, API Platform uses the first `Get` operation defined to generate the IRI of an item and the first `GetCollection` operation to generate the IRI of a collection. + +If your resource does not have any `Get` operation, API Platform automatically adds an operation to help generating this IRI. +If your resource has any identifier, this operation will look like `/books/{id}`. But if your resource doesn’t have any identifier, API Platform will use the Skolem format `/.well-known/genid/{id}`. +Those routes are not exposed from any documentation (for instance OpenAPI), but are anyway declared on the routing system and always return a HTTP 404. + +## Configuring Operations + +The URL, the method and the default status code (among other options) can be configured per operation. + +In the next example, both `GET` and `POST` operations are registered with custom URLs. Those will override the URLs generated by default. +In addition to that, we require the `id` parameter in the URL of the `GET` operation to be an integer, and we configure the status code generated after successful `POST` request to be `301`: @@ -198,22 +209,27 @@ If you do not want to allow access to the resource item (i.e. you don't want a ` // api/src/Entity/Book.php namespace App\Entity; -use ApiPlatform\Action\NotFoundAction; -use ApiPlatform\Metadata\Get; -use ApiPlatform\Metadata\GetCollection; use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\Post; #[ApiResource(operations: [ new Get( - controller: NotFoundAction::class, - read: false, - output: false + uriTemplate: '/grimoire/{id}', + requirements: ['id' => '\d+'], + defaults: ['color' => 'brown'], + options: ['my_option' => 'my_option_value'], + schemes: ['https'], + host: '{subdomain}.api-platform.com' ), - new GetCollection() + new Post( + uriTemplate: '/grimoire', + status: 301 + ) ])] class Book { - // ... + //... } ``` @@ -222,11 +238,19 @@ class Book resources: App\Entity\Book: operations: - ApiPlatform\Metadata\GetCollection: ~ + ApiPlatform\Metadata\Post: + uriTemplate: '/grimoire' + status: 301 ApiPlatform\Metadata\Get: - controller: ApiPlatform\Action\NotFoundAction - read: false - output: false + uriTemplate: '/grimoire/{id}' + requirements: + id: '\d+' + defaults: + color: 'brown' + host: '{subdomain}.api-platform.com' + schemes: ['https'] + options: + my_option: 'my_option_value' ``` ```xml @@ -239,9 +263,25 @@ resources: https://api-platform.com/schema/metadata/resources-3.0.xsd"> - - + + + + \d+ + + + + brown + + + + https + + + + brown + + + @@ -249,12 +289,7 @@ resources: -## Configuring Operations - -The URL, the method and the default status code (among other options) can be configured per operation. - -In the next example, both `GET` and `POST` operations are registered with custom URLs. Those will override the URLs generated by default. -In addition to that, we require the `id` parameter in the URL of the `GET` operation to be an integer, and we configure the status code generated after successful `POST` request to be `301`: +When you do not want to allow access to the resource item (i.e. you don't want a `GET` item operation), instead of omitting the resource item altogether, you can explicitly specify the IRI of the resource item by declaring a `GET` item operation that returns HTTP 404 (Not Found). For example: @@ -263,6 +298,7 @@ In addition to that, we require the `id` parameter in the URL of the `GET` opera // api/src/Entity/Book.php namespace App\Entity; +use ApiPlatform\Action\NotFoundAction; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\Post; @@ -270,11 +306,9 @@ use ApiPlatform\Metadata\Post; #[ApiResource(operations: [ new Get( uriTemplate: '/grimoire/{id}', - requirements: ['id' => '\d+'], - defaults: ['color' => 'brown'], - options: ['my_option' => 'my_option_value'], - schemes: ['https'], - host: '{subdomain}.api-platform.com' + controller: NotFoundAction::class, + read: false, + output: false ), new Post( uriTemplate: '/grimoire', @@ -283,7 +317,7 @@ use ApiPlatform\Metadata\Post; ])] class Book { - //... + // ... } ``` @@ -297,14 +331,9 @@ resources: status: 301 ApiPlatform\Metadata\Get: uriTemplate: '/grimoire/{id}' - requirements: - id: '\d+' - defaults: - color: 'brown' - host: '{subdomain}.api-platform.com' - schemes: ['https'] - options: - my_option: 'my_option_value' + controller: ApiPlatform\Action\NotFoundAction + read: false + output: false ``` ```xml @@ -318,24 +347,8 @@ resources: - - - \d+ - - - - brown - - - - https - - - - brown - - - + diff --git a/symfony/messenger.md b/symfony/messenger.md index 735e1815195..e2ce3dc61bf 100644 --- a/symfony/messenger.md +++ b/symfony/messenger.md @@ -28,13 +28,10 @@ namespace App\Entity; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\ApiProperty; -use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\Post; use Symfony\Component\Validator\Constraints as Assert; -use ApiPlatform\Action\NotFoundAction; #[ApiResource(operations: [ - new Get(controller: NotFoundAction::class, read: false, status: 404), new Post(messenger: true, output: false, status: 202) ])] final class Person @@ -56,18 +53,13 @@ resources: status: 202 messenger: true output: false - ApiPlatform\Metadata\Get: - status: 404 - controller: ApiPlatform\Action\NotFoundAction - read: false ``` Because the `messenger` attribute is `true`, when a `POST` is handled by API Platform, the corresponding instance of the `Person` will be dispatched. -For this example, only the `POST` operation is enabled. We disabled the item operation using the `NotFoundAction`. A resource must have at least one item operation as it must be identified by an IRI, here the route `/people/1` exists, eventhough it returns a 404 status code. -We use the `status` attribute to configure API Platform to return a [202 Accepted HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/202). +For this example, only the `POST` operation is enabled. If the resource does not have any `Get` operation, API Platform [automatically adds an operation to help generating an IRI identify the resource](../core/operations/#enabling-and-disabling-operations). We use the `status` attribute to configure API Platform to return a [202 Accepted HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/202). It indicates that the request has been received and will be treated later, without giving an immediate return to the client. Finally, the `output` attribute is set to `false`, so the HTTP response that will be generated by API Platform will be empty, and the [serialization process](../core/serialization.md) will be skipped. From 62f8d675316b1f8e3ca6b751644d5189ce85ed9c Mon Sep 17 00:00:00 2001 From: Takashi Kanemoto Date: Mon, 22 Sep 2025 17:32:55 +0900 Subject: [PATCH 2/2] tweak --- symfony/messenger.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/symfony/messenger.md b/symfony/messenger.md index e2ce3dc61bf..726e8e68636 100644 --- a/symfony/messenger.md +++ b/symfony/messenger.md @@ -59,7 +59,8 @@ resources: Because the `messenger` attribute is `true`, when a `POST` is handled by API Platform, the corresponding instance of the `Person` will be dispatched. -For this example, only the `POST` operation is enabled. If the resource does not have any `Get` operation, API Platform [automatically adds an operation to help generating an IRI identify the resource](../core/operations/#enabling-and-disabling-operations). We use the `status` attribute to configure API Platform to return a [202 Accepted HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/202). +For this example, only the `POST` operation is enabled. If the resource does not have any `Get` operation, API Platform [automatically adds an operation to help generating an IRI identify the resource](../core/operations/#enabling-and-disabling-operations). +We use the `status` attribute to configure API Platform to return a [202 Accepted HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/202). It indicates that the request has been received and will be treated later, without giving an immediate return to the client. Finally, the `output` attribute is set to `false`, so the HTTP response that will be generated by API Platform will be empty, and the [serialization process](../core/serialization.md) will be skipped.