Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions core/extending.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ The following tables summarizes which extension point to use depending on what y
| [Messenger Handlers](../symfony/messenger.md) | create 100% custom, RPC, async, service-oriented endpoints (should be used in place of custom controllers because the messenger integration is compatible with both REST and GraphQL, while custom controllers only work with REST) |
| [DTOs](dto.md) | use a specific class to represent the input or output data structure related to an operation |
| [Kernel Events](events.md) | customize the HTTP request or response (REST only, other extension points must be preferred when possible) |
| [Operations and Resources](operations.md) | use mutators to dynamically alter metadata (works for third party API endpoints) |

## Doctrine Specific Extension Points

Expand Down
73 changes: 73 additions & 0 deletions core/operations.md
Original file line number Diff line number Diff line change
Expand Up @@ -589,3 +589,76 @@ class Weather
```

That's it!

## Customize Operation and Resource Metadata

Metadata mutators allow a dynamic control over resources and operations, by programmatically altering metadata before they are exposed as endpoints. Providing a way to modify, add or remove operations, adjust serialization groups or pagination settings.

It also makes it possible to customize built-in endpoints from a third-party API, such as Sylius.

### Resource Mutator

Use the resource mutator to modify the entire resource metadata by adding the attribute and target resource class as argument:

```php
<?php
// src/Entity/Book.php
namespace App;

use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\AsResourceMutator;
use ApiPlatform\Metadata\ResourceMutatorInterface;
use App\Entity\User;
use Symfony\Component\DependencyInjection\Attribute\Autowire;

#[AsResourceMutator(resourceClass: Book::class)]
final readonly class UserApiDomainMutator implements ResourceMutatorInterface
{
// .env
// API_PREFIX="/library"
public function __construct(#[Autowire(env: 'API_PREFIX')] private string $apiDomain) {
}

public function __invoke(ApiResource $resource): ApiResource
{
if (!$operations = $resource->getOperations()) {
return $resource;
}

foreach ($operations as $name => $operation) {
// add route prefix to each resource operation
$prefixedOperation = $operation->withRoutePrefix($this->apiDomain);
$operations->add($name, $prefixedOperation);
}

return $resource->withOperations($operations);
}
}
```

### Operation Mutator

The operation mutator will modify a specific operation's metadata, by using the attribute and passing the operation name:

```php
<?php

namespace App\Mutator;

use ApiPlatform\Metadata\AsOperationMutator;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\Metadata\OperationMutatorInterface;

#[AsOperationMutator(operationName: '_api_Book_get_collection')]
final class BookOperationMutator implements OperationMutatorInterface
{
public function __invoke(Operation $operation): Operation
{
$context = $operation->getNormalizationContext() ?? [];
// add another group to normalization group
$context['groups'][] = 'review:list:read';

return $operation->withNormalizationContext($context);
}
}
```