213 lines
6.8 KiB
Plaintext
213 lines
6.8 KiB
Plaintext
---
|
|
description:
|
|
globs:
|
|
alwaysApply: true
|
|
---
|
|
# API Platform dans Mangarr
|
|
|
|
## Structure de l'API
|
|
L'API est organisée dans la couche Infrastructure de chaque domaine :
|
|
|
|
```
|
|
Domain/Manga/Infrastructure/ApiPlatform/
|
|
├── Resource/ # Configuration des ressources API
|
|
│ └── MangaResource.php
|
|
├── State/ # Providers et Processors
|
|
├── Provider/ # State Providers
|
|
└── Processor/ # State Processors
|
|
|
|
```
|
|
|
|
## Règles d'Organisation
|
|
|
|
### 1. Resources
|
|
- Localisation : `Infrastructure/ApiPlatform/Resource/`
|
|
- Principes :
|
|
- Une classe = une ressource API
|
|
- Documentation exhaustive avec les attributs PHP 8
|
|
- Validation contraintes avec les attributs Symfony
|
|
- Nommage : `{Nom}Resource`
|
|
|
|
### 2. State Providers/Processors
|
|
- Localisation : `Infrastructure/ApiPlatform/State/`
|
|
- Principes :
|
|
- Utiliser les cas d'utilisation du domaine (Commands/Queries)
|
|
- Ne pas contenir de logique métier
|
|
- Conversion Resource ↔ Command/Query
|
|
- Nommage : `{Action}{Resource}StateProvider/Processor`
|
|
|
|
## Exemples de Code
|
|
|
|
### 1. Resource API
|
|
```php
|
|
namespace App\Domain\Manga\Infrastructure\ApiPlatform\Resource;
|
|
|
|
use ApiPlatform\Metadata\ApiResource;
|
|
use ApiPlatform\Metadata\Get;
|
|
use ApiPlatform\Metadata\Post;
|
|
use App\Domain\Manga\Infrastructure\ApiPlatform\State\Provider\GetMangaStateProvider;
|
|
use App\Domain\Manga\Infrastructure\ApiPlatform\State\Processor\CreateMangaStateProcessor;
|
|
use Symfony\Component\Validator\Constraints as Assert;
|
|
|
|
#[ApiResource(
|
|
shortName: 'Manga',
|
|
operations: [
|
|
new Get(
|
|
uriTemplate: '/mangas/{id}',
|
|
provider: GetMangaStateProvider::class,
|
|
description: 'Récupère un manga par son identifiant',
|
|
openapi: [
|
|
'summary' => 'Récupère un manga',
|
|
'200' => [
|
|
'description' => 'Manga trouvé',
|
|
'content' => [
|
|
'application/json' => [
|
|
'schema' => [
|
|
'type' => 'object',
|
|
'properties' => [
|
|
'id' => ['type' => 'string', 'format' => 'uuid'],
|
|
'title' => ['type' => 'string'],
|
|
'description' => ['type' => 'string', 'nullable' => true],
|
|
'authors' => [
|
|
'type' => 'array',
|
|
'items' => ['type' => 'string']
|
|
],
|
|
'coverUrl' => ['type' => 'string', 'format' => 'uri', 'nullable' => true]
|
|
],
|
|
'required' => ['id', 'title', 'authors']
|
|
]
|
|
]
|
|
]
|
|
],
|
|
'404' => [
|
|
'description' => 'Manga non trouvé'
|
|
]
|
|
]
|
|
),
|
|
new Post(
|
|
uriTemplate: '/mangas',
|
|
processor: CreateMangaStateProcessor::class,
|
|
description: 'Crée un nouveau manga',
|
|
openapi: [
|
|
'requestBody' => [
|
|
'content' => [
|
|
'application/json' => [
|
|
'schema' => [
|
|
'type' => 'object',
|
|
'properties' => [
|
|
'title' => ['type' => 'string'],
|
|
'description' => ['type' => 'string', 'nullable' => true],
|
|
'authors' => [
|
|
'type' => 'array',
|
|
'items' => ['type' => 'string']
|
|
],
|
|
'coverUrl' => ['type' => 'string', 'format' => 'uri', 'nullable' => true]
|
|
],
|
|
'required' => ['title']
|
|
]
|
|
]
|
|
]
|
|
],
|
|
'responses' => [
|
|
'201' => [
|
|
'description' => 'Manga créé'
|
|
],
|
|
'400' => [
|
|
'description' => 'Données invalides'
|
|
]
|
|
]
|
|
]
|
|
)
|
|
]
|
|
)]
|
|
class MangaResource
|
|
{
|
|
}
|
|
```
|
|
|
|
### 2. State Provider
|
|
```php
|
|
namespace App\Domain\Manga\Infrastructure\ApiPlatform\State\Provider;
|
|
|
|
use ApiPlatform\Metadata\Operation;
|
|
use ApiPlatform\State\ProviderInterface;
|
|
use App\Domain\Manga\Application\Query\GetMangaByIdQuery;
|
|
use App\Domain\Shared\Contract\Response;
|
|
use Symfony\Component\Messenger\MessageBusInterface;
|
|
|
|
class GetMangaStateProvider implements ProviderInterface
|
|
{
|
|
public function __construct(
|
|
private readonly MessageBusInterface $queryBus
|
|
) {}
|
|
|
|
public function provide(Operation $operation, array $uriVariables = [], array $context = []): ?Response
|
|
{
|
|
$query = new GetMangaByIdQuery($uriVariables['id']);
|
|
$response = $this->queryBus->dispatch($query);
|
|
|
|
if (null === $response) {
|
|
return null;
|
|
}
|
|
|
|
return $response;
|
|
}
|
|
}
|
|
```
|
|
|
|
### 3. State Processor
|
|
```php
|
|
namespace App\Domain\Manga\Infrastructure\ApiPlatform\State\Processor;
|
|
|
|
use ApiPlatform\Metadata\Operation;
|
|
use ApiPlatform\State\ProcessorInterface;
|
|
use App\Domain\Manga\Application\Command\CreateMangaCommand;
|
|
use Symfony\Component\Messenger\MessageBusInterface;
|
|
|
|
class CreateMangaStateProcessor implements ProcessorInterface
|
|
{
|
|
public function __construct(
|
|
private readonly MessageBusInterface $commandBus
|
|
) {}
|
|
|
|
public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): void
|
|
{
|
|
assert($data instanceof MangaResource);
|
|
|
|
$command = new CreateMangaCommand(
|
|
title: $data->title,
|
|
description: $data->description,
|
|
authors: $data->authors,
|
|
coverUrl: $data->coverUrl
|
|
);
|
|
|
|
$this->commandBus->dispatch($command);
|
|
}
|
|
}
|
|
```
|
|
|
|
## Bonnes Pratiques
|
|
|
|
### 1. Documentation
|
|
- Documentation exhaustive des endpoints
|
|
- Description claire des paramètres
|
|
- Exemples de requêtes/réponses
|
|
- Documentation des codes d'erreur
|
|
|
|
### 2. Validation
|
|
- Validation stricte des entrées
|
|
- Groupes de validation par contexte
|
|
- Messages d'erreur explicites
|
|
- Validation des types et formats
|
|
|
|
### 3. Sécurité
|
|
- Définition claire des accès
|
|
- Validation des permissions
|
|
- Sanitization des entrées
|
|
- Gestion des erreurs sécurisée
|
|
|
|
### 4. Performance
|
|
- Pagination par défaut
|
|
- Sélection des champs (sparse fieldsets)
|
|
- Gestion des includes (relationships)
|
|
- Cache approprié |