The international conference on the API Platform Framework
The API Platform Conference 2024 is happening soon, and it's close to selling out.
API Platform 4, Caddy web server, Xdebug, AI... Enjoy two days of inspiring talks with our friendly community and our amazing speakers.
To mutate the application states during POST
, PUT
, PATCH
or DELETE
operations, API Platform uses
classes called state processors. State processors receive an instance of the class marked as an API resource (usually using
the #[ApiResource]
attribute). This instance contains data submitted by the client during the deserialization
process.
A state processor using Doctrine ORM is included with the library and is enabled by default. It is able to persist and delete objects that are also mapped as Doctrine entities. A Doctrine MongoDB ODM state processor is also included and can be enabled by following the MongoDB documentation.
However, you may want to:
Custom state processors can be used to do so. A project can include as many state processors as needed. The first able to process the data for a given resource will be used.
If the Symfony MakerBundle is installed in your project, you can use the following command to generate a custom state processor easily:
bin/console make:state-processor
To create a state processor, you have to implement the ProcessorInterface
.
This interface defines a method process
: to create, delete, update, or alter the given data in any ways.
Here is an implementation example:
<?php
namespace App\State;
use App\Entity\BlogPost;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ProcessorInterface;
class BlogPostProcessor implements ProcessorInterface
{
/**
* {@inheritDoc}
*/
public function process($data, Operation $operation, array $uriVariables = [], array $context = [])
{
// call your persistence layer to save $data
return $data;
}
}
We then configure our operation to use this processor:
<?php
namespace App\Entity;
use ApiPlatform\Metadata\Post;
use App\State\BlogPostProcessor;
#[Post(processor: BlogPostProcessor::class)]
class BlogPost {}
If service autowiring and autoconfiguration are enabled (they are by default), you are done!
Otherwise, if you use a custom dependency injection configuration, you need to register the corresponding service and add the
api_platform.state_processor
tag.
# api/config/services.yaml
services:
# ...
App\State\BlogPostProcessor: ~
# Uncomment only if autoconfiguration is disabled
#tags: [ 'api_platform.state_processor' ]
If you want to execute custom business logic before or after persistence, this can be achieved by decorating the built-in state processors or using composition.
The next example uses Symfony Mailer. Read its documentation if you want to use it.
Here is an implementation example which sends new users a welcome email after a REST POST
or GraphQL create
operation, in a project using the native Doctrine ORM state processor:
<?php
namespace App\State;
use ApiPlatform\Metadata\DeleteOperationInterface;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ProcessorInterface;
use App\Entity\User;
use Symfony\Component\Mailer\MailerInterface;
final class UserProcessor implements ProcessorInterface
{
public function __construct(private ProcessorInterface $persistProcessor, private ProcessorInterface $removeProcessor, MailerInterface $mailer)
{
}
public function process($data, Operation $operation, array $uriVariables = [], array $context = [])
{
if ($operation instanceof DeleteOperationInterface) {
return $this->removeProcessor->process($data, $operation, $uriVariables, $context);
}
$result = $this->persistProcessor->process($data, $operation, $uriVariables, $context);
$this->sendWelcomeEmail($data);
return $result;
}
private function sendWelcomeEmail(User $user)
{
// Your welcome email logic...
// $this->mailer->send(...);
}
}
Even with service autowiring and autoconfiguration enabled, you must still configure the decoration:
# api/config/services.yaml
services:
# ...
App\State\UserProcessor:
bind:
$persistProcessor: '@api_platform.doctrine.orm.state.persist_processor'
$removeProcessor: '@api_platform.doctrine.orm.state.remove_processor'
# Uncomment only if autoconfiguration is disabled
#arguments: ['@App\State\UserProcessor.inner']
#tags: [ 'api_platform.state_processor' ]
And configure that you want to use this processor on the User resource:
<?php
namespace App\Entity;
use ApiPlatform\Metadata\ApiResource;
use App\State\UserProcessor;
#[ApiResource(processor: UserProcessor::class)]
class User {}
You can also help us improve the documentation of this page.
Made with love by
Les-Tilleuls.coop can help you design and develop your APIs and web projects, and train your teams in API Platform, Symfony, Next.js, Kubernetes and a wide range of other technologies.
Learn more