Le blog

Sortie de API Platform 3.3

Publié le 30 avril 2024

Nous avons le plaisir d'annoncer la sortie d'API Platform 3.3, et son lot de belles améliorations ! De nouvelles options ont été ajoutées aux classes de métadonnées, ainsi qu'un focus accru sur le RDF au cœur de la conception de l'API et un objectif de rendre API Platform plus compatible avec Laravel.

Un grand merci à chaque contributrice et contributeur permettant de rendre l'usage d'API Platform de plus en plus agréable. Ne manquez pas de vous inscrire à l'API Platform Conference 2024 : le programme est prêt à sortir le 14 mai, et nous avons hâte que vous le découvriez ! Il ne reste que très peu de tickets au tarif Early Bird, rejoignez-nous les 19 et 20 septembre, de beaux retours d'expériences et cas d'usage seront partagés à Lille pour la quatrième année consécutive.

" class="wp-image-8045" style="aspect-ratio:3/2;object-fit:cover

Cet article revient sur les changements majeurs de cette version 3.3, pour plus de détails regardez notre changelog.

Formats #

Nous avons décidé de déprécier le fait de ne pas définir l'option formats sur API Platform. Nous sommes convaincus que lors de l'utilisation du framework, vous devriez utiliser un format hypermédia tel que JSON-LD ou JSON:API. Nous ne recommandons pas le JSON brut.

Métadonnées #

Les attributs de métadonnées (ApiResource et verbes HTTP) disposent d'une nouvelle option headers :

php
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Get;


#[ApiResource(
	headers: ['Location' => '/foobar', 'Hello' => 'World'],
	status: 301,
	output: false,
	operations: [
    	new Get(uriTemplate: '/redirect_to_foobar'),
	],
)]

L'option Link dispose d'une option security permettant de lier les valeurs représentées par toProperty ou fromProperty :

php
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\Link;


#[Get(
	uriTemplate: '/employees/{employeeId}/company',
	uriVariables: [
    	'employeeId' => new Link(fromClass: Employee::class, toProperty: 'company', security: "is_granted(some_voter, company)"),
	],
)]

Nous avons également amélioré le contexte de sécurité sur ApiProperty en ajoutant le nom de propriété dans son contexte.

Si notre système de liaison automatique ne répond pas à vos besoins, vous pouvez accrocher un service qui gère les liens. Son interface est spécifique au système de persistance et peut être plus rapide à configurer qu'un provider.

Enfin, il y a une nouvelle fonction d'Expression Language get_operation qui peut être utilisée sur Mercure :

php
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\UrlGeneratorInterface;


#[ApiResource(
	// ...
	mercure: [
    	'topics' => [
        	'@=iri(object)',
        	'@=iri(object, '.UrlGeneratorInterface::ABS_URL.', get_operation(object, "/foos/bars/{id}{._format}"))'
    	],
	]
)]

Cela améliore la génération des IRI car vous pouvez choisir l'opération à partir de laquelle vous souhaitez obtenir l'IRI a propager.

Paramètres #

Un nouvel attribut est introduit nommé Parameter. Il existe deux variantes : QueryParameter et HeaderParameter, ce qui permet une plus grande flexibilité concernant la façon dont les filtres sont appelés sur les ressources d'API Platform.

php
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\QueryParameter;


#[GetCollection(
	uriTemplate: 'orders',
	parameters: [
    	'order[:property]' => new QueryParameter(filter: 'offer.order_filter'),
	]
)
class Offer {
	public string $id;
	public string $name;
}

Découvrez l’étendue des possibilités des paramètres dans la documentation. Notez que la validation des paramètres utilise le Validator de Symfony ; vous pouvez soit lier des contraintes, soit spécifier une documentation (OpenAPI, Hydra, JSON Schema) et nous ajouterons automatiquement des contraintes en fonction de votre input.

Cache #

API Platform dispose d'un mécanisme d'invalidation basé sur les IRI qu'il collecte automatiquement lors de la sérialisation. Lorsque vous avez des besoins spécifiques, il n'était pas facile de spécifier quelles IRI vous voulez invalider. Pour ce faire, nous avons introduit une nouvelle interface TagCollectorInterface pour aider à collecter des IRI spécifiques :

php
use ApiPlatform\Serializer\TagCollectorInterface;


final class TagCollectorDefault implements TagCollectorInterface
{
   public function collect(array $context = []): void
   {
       if (isset($context['property_metadata'])) {
           return;
       }


       $iri = $context['iri'];


       if (isset($context['resources']) && isset($iri)) {
           $context['resources'][$iri] = $iri;
       }
   }
}

Nous vous conseillons de lire l’implémentation du code si vous souhaitez plus de détails sur son fonctionnement.

Documentation #

Hydra

Désormais, nous lisons hydra:property s'il existe dans le jsonLdContext et utilisons sa valeur directement dans la documentation :

php
use ApiPlatform\Metadata\ApiProperty;


#[ApiProperty(jsonLdContext: ['hydra:property' => ['rdfs:label' => 'change this value', 'owl:maxCardinality' => 5]]);

Avant, seul @type était lu.

OpenAPI

Une nouvelle option est disponible pour contrôler si API Platform ajoute automatiquement des réponses OpenAPI ou non. Vous pouvez soit utiliser la configuration globale api_platform.openapi.overrideResponses (true par défaut), soit spécifier une propriété supplémentaire sur vos opérations :

php
use ApiPlatform\Metadata\Post;
use ApiPlatform\OpenApi\OpenApiFactory;
use ApiPlatform\OpenApi\Model as OpenApi;

#[Post(
   uriTemplate: '/override_open_api_responses',
   openapi: new Operation(
       responses: [
           '204' => new Response(
               description: 'User activated',
           ),
       ]
   ),
   extraProperties: [OpenApiFactory::OVERRIDE_OPENAPI_RESPONSES => false],
)]

Aucune autre réponse ne sera ajoutée par API Platform, n'oubliez pas d'ajouter des réponses d'erreur.

Dépréciations #

Ces namespaces ont été dépréciés :

  •  ApiPlatform\Api
  •  ApiPlatform\Exception
  •  ApiPlatform\Problem
  •   ApiPlatform\Action
  •   ApiPlatform\Util

Les classes publiques se trouvent désormais dans le namespace Metadata.

To listen or not to listen #

Suite au travail effectué pour apporter le support de Laravel, nous avons renforcé notre attention sur la division d'API Platform en plusieurs composants. Vous pouvez installer api-platfom/json-schema ou api-platform/openapi sans l'ensemble du framework si vous avez seulement besoin de ce sous-ensemble de fonctionnalités.

En plus de celà, les écouteurs d'événement HTTP Kernel sont spécifiques à Symfony et comme notre mécanisme Provider/Processor est assez puissant, nous introduisons une façon de supprimer complètement les listeners en faveur de l'utilisation exclusive des providers. C'est génial car nous partagerons plus de code entre tous les sous-systèmes (Laravel, GraphQL, etc.). Les event listeners ne sont pas dépréciés mais si vous souhaitez les utiliser, ou si vous avez besoin des controllers de Symfony, vous devrez activer les listeners en utilisant :

php
api_platform:
   use_symfony_listeners: true

Cela réactive les listeners. Le ReadListener appelle uniquement le ReadProvider, donc la décoration du provider fonctionnera toujours. Cela est valable pour chaque événement, chaque événement possède un provider utilisant le même nom.

Correctifs #

De nombreux correctifs ont été effectués sur cette version mineures pour apporter une meilleure expérience en tant que développeur·se, tel que ne pas sérialiser l'objet Request dans le contexte de Messenger, mettre à jour le MissingConstructorArgumentsException message pour le rendre plus informatif.

Partagez-nous vos retours sur la sortie de cette nouvelle version ! N'oubliez pas de vous inscrire à notre conférence prévue en septembre prochain, et enfin Les-Tilleuls.coop reste toujours disponible pour vous accompagner dans vos projets de migration de version.

Antoine Bluchet

Antoine Bluchet

Principal developer

Mots-clésAPI Platform, Documentation, Laravel

Le blog

Pour aller plus loin