Sortie d'API Platform 4.1 : la documentation au cœur de la découvrabilité des API
Publié le 04 mars 2025
Nous sommes ravis de vous annoncer la disponibilité immédiate de la version 4.1 d'API Platform ! API Platform est un framework centré sur les standards des API, aidant les développeurs et développeuses à les maintenir et à les exploiter. Avec API Platform 4.1, nous mettons l’accent sur l’amélioration de la prise en charge des spécifications Hydra, OpenAPI et JSON Schema. Découvrons dans cet article ces différentes évolutions. Ce billet est aussi disponible dans sa langue d'origine ici.

Améliorations d’OpenAPI
Il est désormais possible de décliner une même spécification OpenAPI en plusieurs versions en utilisant le tag x-apiplatform-tags
:
use ApiPlatform\OpenApi\Factory\OpenApiFactory;
#[GetCollection(openapi: new Operation(extensionProperties: [OpenApiFactory::API_PLATFORM_TAG => ['customer', 'developer']]))]
#[Post(openapi: new Operation(extensionProperties: [OpenApiFactory::API_PLATFORM_TAG => 'developer']))]
class Book {}
Ensuite, utilisez soit le paramètre de requête pour la version web, comme /docs?filter_tags[]=customer
, soit via la ligne de commande :
bin/console api:openapi:export --filter-tags=customer
Cela produira une spécification incluant uniquement les opérations correspondant à votre tag.
Avec l'amélioration de notre implémentation de la spécification Problem Detail dans la version 4.0 et la possibilité de déclarer des erreurs comme des ressources API, nous avons franchi un pas de plus vers la possibilité de documenter leur schéma JSON. Depuis la version 3.4, il était déjà possible d’ajouter des erreurs à la documentation d’une opération.
#[GetCollection(errors: [MyDomainException::class])]
class Greeting
{
// ...
}
Cela est maintenant également activé pour toutes les réponses standard que nous supportons. Par exemple, une erreur 422 (Unprocessable entity
) est désormais documentée dans tous les formats supportés :

Le schéma JSON associé à une erreur est également disponible avec une documentation plus agréable :

Hydra
Le patch Hydra modifie le hydra:title
par défaut et utilise la ressource shortname
. Auparavant, l'information hydra:title
dupliquait celle de hydra:description
. Le rdfs:label
a été supprimé de la hydra:Class
, car il était utilisé à la place de hydra:title
. Sur hydra:property
, rdfs:label
a été renommé en label
, car le namespace rdfs
est désormais disponible dans le contexte.
Les classes ApiPlatform\Metadata\ErrorResource
et ConstraintViolation
(de la classe ValidationException
) sont maintenant générées directement à partir de vos classes PHP. Seule la ConstraintViolationList
est définie en dur et documente la propriété ConstraintViolation::violation
. Par conséquent, vos propres ressources d'erreur sont également documentées. De plus, nous avons maintenant défini rdfs:subClassOf
sur hydra:Error
.
Il est possible de masquer une opération Hydra (avec #[Get(hideHydraOperation: true)]
), et de sauter une propriété documentée en utilisant #[ApiProperty(hydra: false)]
sur une classe.
Sur les opérations d'écriture, nous avons ajouté le champ expectsHeader
.
Paramètres de requête et filtrage
Vous pouvez désormais configurer API Platform pour qu'il envoie une erreur de validation lorsqu'un paramètre de requête est utilisé sur votre API alors qu'il n'est pas pris en charge. Pour cela, activez strictQueryParameters: true
(globalement via les paramètres par défaut, ou au niveau d’une ressource ou d’une opération). En plus de cela, Vincent Amstoutz et moi-même avons travaillé sur l'amélioration de la déclaration des filtres Symfony au sein des paramètres de requête.
#[GetCollection(
parameters: [
'enabled' => new QueryParameter(
filter: new BooleanFilter(),
property: 'active',
),
],
)]
#[ORM\Entity]
class FilteredBooleanParameter
{
}
Auparavant, un filtre devait être un service Symfony ; désormais, c'est une instance statique. Un filtre est un callback où vous devez avoir tout ce qui est nécessaire pour effectuer le filtrage :
public function apply(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, ?Operation $operation = null, array $context = []): void;
Par conséquent, vous ne devriez pas avoir besoin d'injection de dépendances. Nous ne prévoyons pas de déprécier l'utilisation d'un service, mais nous estimons que cette approche est plus conviviale et qu'elle améliore également le découplage de la documentation d'un paramètre. Pour cela, vous disposez de deux nouvelles interfaces : ApiPlatform\Metadata\JsonSchemaFilterInterface
et ApiPlatform\Metadata\OpenApiParameterFilterInterface
use ApiPlatform\Metadata\OpenApiParameterFilterInterface;
use ApiPlatform\Metadata\JsonSchemaFilterInterface;
public class MyDateFilter implements JsonSchemaFilterInterface, OpenApiParameterFilterInterface
/**
* @return array<string, string>
*/
public function getSchema(Parameter $parameter): array
{
return ['type' => 'date'];
}
public function getOpenApiParameters(Parameter $parameter): OpenApiParameter|array|null
{
$in = $parameter instanceof QueryParameter ? 'query' : 'header';
$key = $parameter->getKey();
return [
new OpenApiParameter(name: $key.'[after]', in: $in),
new OpenApiParameter(name: $key.'[before]', in: $in),
new OpenApiParameter(name: $key.'[strictly_after]', in: $in),
new OpenApiParameter(name: $key.'[strictly_before]', in: $in),
];
}
Le paramètre OpenAPI utilisera le getSchema
si aucun schéma n'est fourni. Cela offre plus de contrôle sur un filtre sans avoir à copier ce filtre simplement pour modifier une partie de la documentation.
Laravel
Avec la prise en charge de Laravel 12 (^4.0.19), un BooleanFilter
a été ajouté, et nous enregistrons automatiquement la Policy du modèle lorsqu'elle est trouvée. Nous avons amélioré la prise en charge générale d'Eloquent. Le cache par défaut de nos Métadonnées a été défini sur le cache de fichiers, car il est plus approprié que d'utiliser le cache global (vous pouvez toujours changer cela). Un grand merci à toitzi et amermchaudhary pour avoir fourni de nombreuses corrections depuis la sortie du support de Laravel en septembre dernier !
Et bien plus encore
Jérôme Tamarelle de chez MongoDB a amélioré l'utilisation générale de la mémoire de notre provider de collections MongoDB ! Elasticsearch 7 est de nouveau pris en charge, nous pouvons configurer la profondeur maximale des requêtes GraphQL et la complexité maximale des requêtes, et bien plus encore ! Découvrez le détail de cette release directement sur GitHub, et merci encore à chaque contributeur !
Et les prochaines releases ?
Nous travaillons sur l'ajout de nouveaux filtres et la refactorisation de notre SearchFilter
. Nous nous concentrerons également sur la génération de schémas JSON, car ils sont encore loin d'être parfaits, notamment parce que nous avons étudié une belle optimisation où nous mutualisons les schémas avec des schémas de base par format : jetez un coup d'œil ici. En parallèle, nous travaillons sur un client HTTP Hypermedia qui est encore en phase d'expérimentation.
Toujours concernant API Platform, il reste désormais moins de vingt jours pour soumettre un sujet à notre CFP ! Rendez-vous sur la page de l'événement pour découvrir les différentes thématiques attendues, et rendez-vous courant mai pour découvrir la programmation de cette édition qui marquera les 10 ans du framework.