Retour sur la conférence de Clément Talleau "API Platform, des développeurs d'attributs ?"

Ahmed Eben Hassine
Ahmed Eben hassine
14 octobre 2024

Avec l'arrivée de PHP 8, une nouvelle fonctionnalité a révolutionné la manière dont nous gérons les métadonnées dans nos projets : les attributs. Ces derniers remplacent les annotations traditionnelles basées sur des docblocks, souvent perçues comme complexes et peu optimales. Dans cet article, nous explorerons les avantages des attributs en PHP, ainsi que leur utilisation dans API Platform, illustrée par des exemples concrets.

Préparez-vous à découvrir comment ces changements peuvent simplifier votre code et améliorer vos performances !

 

API Platform, des développeurs d'attributs ? 

Présenté par Clément Talleu 

 

Clément Talleau

 

Une nouvelle approche pour gérer les métadonnées

Les premiers pas des attributs

Les attributs en PHP ont pour objectif de remplacer les annotations basées sur des docblocks, couramment utilisées dans la documentation phpdoc ou dans des bibliothèques telles que doctrine/annotation et Symfony. Ils permettent d'ajouter des métadonnées directement aux classes, méthodes et propriétés. Cette approche simplifie considérablement la gestion des configurations, en remplaçant les anciennes annotations. Voici quelques avantages notables qui font des attributs un choix judicieux :

  • Performance améliorée : Les attributs sont gérés dès la compilation, contrairement aux annotations qui nécessitent un parsing au runtime. Cela optimise le temps d’exécution de votre application, rendant votre code plus réactif.
  • Accès rapide aux métadonnées : Les métadonnées étant intégrées directement dans le code, leur accès est plus rapide et efficace grâce à l'API Reflection. Plus besoin de jongler avec des formats comme XML ou YAML pour stocker vos données !

 

Historique des attributs dans PHP

 

Les Attributes ont d'abord été proposés en 2016 par Dmitry Stogov, mais leur syntaxe initiale, utilisant les symboles <<>>, a été rejetée. Pour en savoir plus sur cette première tentative, consultez le RFC de Dmitry Stogov, le même auteur de l'RFC Just in Time.

Par la suite, la syntaxe a été révisée et présentée sous la forme @@ dans une autre RFC soumise par Michał Brzuchalski en 2019.

Enfin, le 4 mai 2020, Benjamin Eberlei a clôturé le vote sur sa RFC Attributes v2, qui a recueilli 51 voix pour et 1 contre. Cela a permis d'intégrer définitivement les attributs dans PHP 8 avec la syntaxe #[Attribute].

 

Les acteurs clés

  • Benjamin Eberlei : A proposé la RFC en 2020, contribuant ainsi à l'intégration des attributs dans PHP 8.0.
  • Dimitri Catrina : A joué un rôle actif dans la discussion sur les annotations et a soutenu la transition vers les attributs, mettant en avant les avantages de cette nouvelle approche.

 

Une influence de Facebook

L'impact du framework Hack développé par Facebook, qui a introduit des concepts similaires aux attributs sous le nom d'Attributes, a également été déterminant dans la conception des attributs en PHP. Cette innovation a mis en lumière l'importance d'une approche plus intégrée pour gérer les métadonnées.

facebook

Les attributs dans API Platform

Configuration et personnalisation des ressources

Api Platform Logo

API Platform tire parti des attributs pour configurer et personnaliser le comportement des ressources exposées par l'API. Ces attributs sont cruciaux pour définir divers éléments, notamment les routes, les paramètres de requête et les opérations disponibles. Voici une présentation des attributs clés utilisés dans Symfony, ainsi que ceux spécifiques à API Platform :

Attributs spécifiques à API Platform

  • #[ApiResource] : Indique qu'une classe est une ressource exposée par l'API.
  • #[Get], #[Post], #[Put], #[Patch] : Spécifient les méthodes HTTP autorisées pour une ressource.
  • #[ApiFilter(SearchFilter::class, properties: ['name' => 'partial']) : Permet de filtrer les ressources par correspondance partielle.
  • #[HeaderParameter], #[QueryParameter] : Définit les paramètres d’en-tête et de requête pour les opérations.

Opérations GraphQL

  • #[Query] : Pour interroger une ressource.
  • #[QueryCollection] : Pour interroger une collection de ressources.
  • #[Mutation(name: 'create')], #[Mutation(name: 'update')], #[DeleteMutation(name: 'delete')] : Gère les mutations appliquées aux ressources, notamment la création, la mise à jour et la suppression.

Attributs utilisés par Symfony:

  • #[Route] : Définit le chemin de la route pour une opération.
  • #[Assert] : Utilisé pour la validation des données entrantes.
  • #[Cache] : Gère la mise en cache des réponses.
  • #[AsCommand], #[AsDecorator], #[AsMessageHandler], #[Lazy], #[AsController] : Divers attributs pour la gestion des services et des commandes.

En résumé, Symfony comprend plus de 150 attributs répartis à travers ses différents composants, ainsi que plus de 20 attributs spécifiques à API Platform. Pour davantage de détails, n'hésitez pas à consulter l'aperçu proposé dans la documentation : Symfony Attributes Overview.

 

Exemples concrets d'utilisation

Prenons un exemple pour illustrer comment ces attributs se traduisent dans le code :

use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\Post;

#[ApiResource]
#[Get]
#[Post]
class Product
{
    public ?int $id = null;
    public string $name;
    public float $price;
}

Dans cet exemple, la classe Product est configurée pour être exposée par l'API, et les méthodes HTTP autorisées sont définies grâce aux attributs. 

 

Gestion des erreurs et sécurité

Lors de sa présentation, Clément nous a également dévoilé d'autres attributs passionnants, qui vont au-delà de la simple gestion des ressources. Ces attributs sont essentiels pour assurer la sécurité et la gestion des erreurs de votre API :

  • #[IsGranted] : Cet attribut permet de contrôler l'accès à vos ressources, garantissant que seules les personnes autorisées peuvent y accéder.
  • #[ErrorResource]: Utilisé pour configurer le code d'état des exceptions, permettant ainsi une gestion fine des erreurs au sein de votre API.
  • #[NotExposed] : Cet attribut indique qu'une ressource n'est pas exposée au niveau de la documentation OpenAPI

Ces fonctionnalités assurent non seulement le bon fonctionnement de votre API, mais aussi sa sécurité, ce qui est primordial dans le développement moderne.

 

Gestion des exceptions personnalisées

Un exemple intéressant que Clément a partagé est l'utilisation de l'attribut#[WithLogLevel]:

namespace App\Exception;

use Psr\Log\LogLevel;
use Symfony\Component\HttpKernel\Attribute\WithLogLevel;

#[WithLogLevel(LogLevel::WARNING)]
class CustomException extends \Exception

Ici, nous définissons une exception personnalisée, CustomException, qui utilise cet attribut pour s'assurer que les messages de l'exception sont loggés avec le niveau de gravité WARNING. C'est un excellent moyen de garder un œil sur les problèmes potentiels sans encombrer vos logs.

 

Validation des données

Clément a également mentionné l'attribut #[Assert\Luhn], qui est  très utile pour valider les numéros de carte de crédit. Cet attribut garantit qu'un numéro de carte respecte l'algorithme Luhn, ce qui est une première étape essentielle avant d'interagir avec un système de paiement.

 

Lecture des attributs via Meta Factory

Lecture des attributs via Meta Factory

Pour couronner le tout, API Platform utilise le Meta Factory pour lire et manipuler les attributs. Ce processus permet d'accéder aux métadonnées associées aux ressources. Grâce à des classes comme AttributePropertyMetadataFactory, Attributes, ResourceMetadataCollectionFactory et LinkFactory, il devient facile de gérer vos configurations.

Personnalisation des options

API Platform offre également de nombreuses options pour personnaliser votre configuration. Par exemple, concernant la pagination :

L'attribut de pagination peut être configuré pour activer ou désactiver la pagination dans vos collections. Voici un petit aperçu :

#[ApiResource(paginationClientEnabled: false)]
class ProductCollection

En arrière-plan, l'attribut impacte la méthode getEnabled(), qui permet de contrôler à son tour si la pagination gérée par le client est activée ou désactivée. Cela vous offre un moyen de désactiver la pagination côté client si nécessaire.

En résumé, API Platform propose une gamme d'attributs qui rendent la gestion des erreurs et la sécurité à la fois plus simple et plus élégante. Ces outils offrent une approche moderne et efficace pour assurer la fiabilité de vos API.

Création d'attributs personnalisés

Étapes pour créer un attribut

Il est possible de créer un attribut #[\Attribute et de l'utiliser pour annoter les éléments de notre code. Voici un exemple de création d’un attribut :

#[\Attribute(\Attribute::TARGET_CLASS)]
class Encrypt
{
  public function __construct(public ?array $properties = [])
  {}
}

Cet attribut pourrait être utilisé pour chiffrer des données avant de les persister dans la base de données.
Pour l'exploiter avec API Platform, il suffit de l'annoter sur une classe

Application dans API Platform
#[ApiResource]
#[Encrypt(properties:[‘name’,)]
class SecretData
{
    public ?int $id = null;
    public string $name;
}

Enfin, pour décrypter la propriété reçue à travers la requête lors de la dénormalisation des données, il est nécessaire de créer un StateProcessor et un Normalizer.

 

Conclusion

La présentation de Clément Talleau sur les attributs en PHP et leur utilisation dans API Platform nous montre à quel point ils apportent une approche moderne et efficace pour gérer les métadonnées et les configurations. Ces attributs offrent beaucoup d'avantages par rapport aux annotations en termes de performance et de simplicité d'utilisation.

 

À la recherche d'une nouvelle opportunité ? Voir toutes les offres
Découvrez quelques uns de nos projets Symfony Voir les projets

A lire aussi

Voir tous les articles