diff --git a/core/state-processors.md b/core/state-processors.md index e1aec6d02dc..a8e69c25051 100644 --- a/core/state-processors.md +++ b/core/state-processors.md @@ -5,10 +5,13 @@ classes called **state processors**. State processors receive an instance of the the `#[ApiResource]` attribute). This instance contains data submitted by the client during [the deserialization process](serialization.md). -A state processor using [Doctrine ORM](https://www.doctrine-project.org/projects/orm.html) is included with the library and +With the Symfony variant, a state processor using [Doctrine ORM](https://www.doctrine-project.org/projects/orm.html) 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](https://www.doctrine-project.org/projects/doctrine-orm/en/current/reference/basic-mapping.html). A [Doctrine MongoDB ODM](https://www.doctrine-project.org/projects/mongodb-odm.html) state processor is also included and can be enabled by following the [MongoDB documentation](mongodb.md). +With the Laravel variant, a state processor using [Eloquent ORM](https://laravel.com/docs/eloquent) is included with the library and +is enabled by default. It is able to persist and delete objects that are also mapped as [Related Models](https://laravel.com/docs/eloquent-relationships#inserting-and-updating-related-models). + However, you may want to: * store data to other persistence layers (Elasticsearch, external web services...) @@ -20,6 +23,7 @@ process the data for a given resource will be used. ## Creating a Custom State Processor +### Custom State Processor with Symfony If the [Symfony MakerBundle](https://symfony.com/doc/current/bundles/SymfonyMakerBundle) is installed in your project, you can use the following command to generate a custom state processor easily: ```console @@ -75,8 +79,64 @@ use App\State\BlogPostProcessor; class BlogPost {} ``` +### Custom State Processor with Laravel +Using [Laravel Artisan Console](https://laravel.com/docs/artisan), you can generate a custom state processor easily with the following command: +```console +php artisan make:state-processor +``` + +To create a state processor, you have to implement the [`ProcessorInterface`](https://github.com/api-platform/core/blob/main/src/State/ProcessorInterface.php). +This interface defines a method `process`: to create, delete, update, or alter the given data in any ways. + +Here is an implementation example: + +```php + + */ +final class BlogPostProcessor implements ProcessorInterface +{ + /** + * @return BlogPost|void + */ + public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): mixed + { + // call your persistence layer to save $data + return $data; + } +} +``` + +The `process()` method must return the created or modified object, or nothing (that's why `void` is allowed) for `DELETE` operations. +The `process()` method can also take an object as input, in the `$data` parameter, that isn't of the same type that its output (the returned object). See [the DTO documentation entry](dto.md) for more details. + +We then configure our operation to use this processor: + +```php + + */ +final class UserProcessor implements ProcessorInterface +{ + public function __construct( + private ProcessorInterface $persistProcessor, + private ProcessorInterface $removeProcessor, + ) + { + } + + /** + * @return User|void + */ + public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): mixed + { + 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): void + { + // Your welcome email logic... + // Mail::to($user->getEmail())->send(new WelcomeMail($user)); + } +} +``` + +Don't forget to tag the service with the `PersistProcessor` and the `RemoveProcessor` state classes. + +```php +app->tag([UserProcessor::class], [PersistProcessor::class, RemoveProcessor::class,]); + } + + public function boot(): void + { + } +} +``` +If you're using Laravel MongoDB ODM instead of Eloquent ORM, make sure you're using the right services. + +Finally, configure that you want to use this processor on the User resource: + +```php +