Operations

API Platform relies on the concept of operations. Operations can be applied to a resource exposed by the API. From an implementation point of view, an operation is a link between a resource, a route and its related controller.

Operations screencast
Watch the Operations screencast

API Platform automatically registers typical CRUD operations and describes them in the exposed documentation (Hydra and Swagger). It also creates and registers routes corresponding to these operations in the Symfony routing system (if it is available).

The behavior of built-in operations can be seen in the Declare a Resource guide.

The list of enabled operations can be configured on a per-resource basis. Creating custom operations on specific routes is also possible. We see an Operation as a method, URI Template, type (dictionnary vs collection) tuple. Indeed the ApiPlatform\Metadata\GetCollection implements the ApiPlatform\Metadata\CollectionOperationInterface, meaning that it returns a collection.

When the ApiPlatform\Metadata\ApiResource attribute is applied to a PHP class, the following built-in CRUD operations are automatically enabled:

MethodClassMandatory*Description
GETApiPlatform\Metadata\GetCollectionyesRetrieve the (paginated) list of elements
POSTApiPlatform\Metadata\PostnoCreate a new element
GETApiPlatform\Metadata\GetyesRetrieve an element
PUTApiPlatform\Metadata\PutnoReplace an element
PATCHApiPlatform\Metadata\PatchnoApply a partial modification to an element
DELETEApiPlatform\Metadata\DeletenoDelete an element

*These operations are mandatory as they play a role in IRI generation.

If no operation is specified, all default CRUD operations are automatically registered. It is also possible - and recommended for large projects - to define operations explicitly.

Keep in mind that once you explicitly set up an operation, the automatically registered CRUD will no longer be. If you declare even one operation manually, such as #[ApiPlatform\Metadata\Get], you must declare the others manually as well if you need them.

Operations can be configured using annotations, XML or YAML. In the following examples, we enable only the built-in operation read operations for both a collection of books and a single book endpoint.

<?php
// api/src/Entity/Book.php
namespace App\Entity;
 
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\GetCollection;
 
#[ApiResource(operations: [
    new Get(),
    new GetCollection()
])]
class Book
{
    // ...
}
<?php
// api/src/Entity/Book.php
namespace App\Entity;
 
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\GetCollection;
 
#[ApiResource(operations: [
    new Get(),
    new GetCollection()
])]
class Book
{
    // ...
}

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:

<?php
// api/src/Entity/Book.php
namespace App\Entity;
 
use ApiPlatform\Action\NotFoundAction;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\ApiResource;
 
#[ApiResource(operations: [
    new Get(
        controller: NotFoundAction::class,
        read: false,
        output: false,
        openapi: false
    ),
    new GetCollection()
])]
class Book
{
    // ...
}
<?php
// api/src/Entity/Book.php
namespace App\Entity;
 
use ApiPlatform\Action\NotFoundAction;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\ApiResource;
 
#[ApiResource(operations: [
    new Get(
        controller: NotFoundAction::class,
        read: false,
        output: false,
        openapi: false
    ),
    new GetCollection()
])]
class Book
{
    // ...
}

Copyright © 2023 Kévin Dunglas

Sponsored by Les-Tilleuls.coop