Cours de Rémi JarjatCours de Rémi Jarjat
  • Liste des cours
  • Culture numérique
  • Git
    • Terminologie
    • Avant de commencer
    • Créer un dépôt (local)
    • Enregistrer des changements
    • Des branches
    • Mise en commun du travail
    • Annuler des changements
    • Réécrire l'historique
    • Des outils pour se simplifier Git
    • Exercices
    • Exemples pratiques
  • Linux
    • Installation
    • Historique
    • Rangement des fichiers
    • Les processus
    • Commandes de base
    • Commandes avancées
    • /linux/6-other-technologies.html
    • Exercices
    • Correction des exercices
  • PHP
    • Environnement de travail
    • Bases du PHP
    • Tests et boucles
    • Procédures et fonctions
    • Interagir avec l'utilisateur
    • La temporisation de sortie
    • PHP Doc et PSR
    • PHP Orienté objet
    • Héritage et objets
    • Factorisation
    • Manipuler la BdD avec PDO (PHP Data Object)
    • Architecture MVC
    • Webservices REST
    • Exercices - Bases
    • Exercices - Séparer en plusieurs fichiers
    • Exercices - POST et SESSION
    • Exercices - Panier et validation
    • Exercices - Objets
    • Exercices - BdD avec PDO
    • Projet - montage d'ordinateurs
    • Projet - Personnages de Jeux de Rôle
  • Symfony
    • Installer Symfony et son environnement de travail
    • Structure et utilisation d'un projet
    • Le routing
    • Les controllers
    • Twig
    • Les services et l'injection de dépendances
    • Doctrine et la BdD
    • Formulaires
    • Les traductions
    • Event listeners/subscribers
    • Connexion et sécurisation
    • Bundles
    • Easy Admin Bundle
    • API Platform
    • Pense-bêtes
    • Symfony au quotidien
    • Travailler avec Docker
    • Projet : annonces de SPA / éleveurs
    • Exercices
  • Javascript
    • Les bases du langage
    • Manipulation logique
    • Le DOM
    • JQuery
    • Ajax
    • Programmation orientée objet
    • Webpack
    • Outils utiles
    • Révisions
  • Serveur Lamp
  • Déploiement
    • Des outils et manières de faire
    • Déploiement par FTP
    • Wordpress
    • Intégrer Git dans le processus
    • GitHub Pages pour déployer facilement
    • Symfony et Angular
  • Docker
  • Intégration continue
  • Sécurité informatique

API Platform

  • En résumé
  • La sérialisation
  • Mettre en place une API avec API Platform
  • Aller plus loin
    • Personnaliser les propriétés renvoyées
    • Validation des données

Cette partie concerne des bases d'API Platform, nous n'allons pas évoquer de fonctionnalités avancées et resterons sur les notions de base, pour créer une API simple rapidement.

La documentation officielle

Un tutoriel très complet sur API Platform (grandement recommandé) sur lequel je me suis basé pour l'écriture de ce cours.

En résumé

  • Pour créer une API rapidement, on utilise API Platform (mais ça n'est pas le seul moyen disponible)
  • On personnalise notre API via de la configuration (principalement annotations / attributs)
  • Une documentation est directement générée (peut être utilisée dans plusieurs formats : Swagger ou ReDoc)
  • On peut personnaliser les propriétés disponibles dans l'API avec des annotations / attributs dans nos entités (on associe des groupes de sérialisation)
  • On peut valider les données entrées à l'aide d'annotations / d'attributs

La sérialisation

Le processus de sérialisation est lié à Symfony et API Platform l'exploite pour ses propres besoins. Commençons par quelques définitions :

  • La sérialisation est la conversion d'un objet PHP en un autre format, en général un format de communication (JSON, Xml, etc)
  • La dé-sérialisation est l'opération inverse : on récupère une donnée JSON (ou équivalent) et on la convertit en objet(s) PHP

Ces opérations de (dé)sérialisation sont composées d'opérations intermédiaires :

  • La normalisation est l'opération de conversion d'un objet PHP en tableau
  • La dé-normalisation est l'opération de conversion d'un tableau en objet PHP
  • L'encodage est l'opération de conversion d'un tableau en un format de communication (JSON, Xml, etc)
  • Le décodage est l'opération de conversion depuis un format de communication (JSON, Xml, etc) en un tableau PHP

Schéma récapitulatif (venu de la documentation d'API Platform sur la sérialisation) :

Mettre en place une API avec API Platform

Nous partons du principe que nous allons initialiser une API dans une application Symfony existante (créée avec symfony new --webapp par exemple).

Dans un tel projet, il faut installer API Platform : composer require api

Une fois cela fait, il faut préciser à API Platform quelles entités nous voulons utiliser dans notre API. Pour cela, il suffit d'ajouter une annotation/un attribut APIResource dans votre entité :

<?php
// api/src/Entity/Test.php

namespace App\Entity;

use ApiPlatform\Metadata\ApiResource;
use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity]
#[APIResource]
class Test 
{
    #[ORM\Column]
    protected string $property = "";
    // ...
}

Plus qu'à vider le cache (php bin/console cache:clear) et aller sur la route /api/doc et il est possible de voir les routes fraîchement créées et les tester.

Répéter l'opération sur différentes entités et une bonne base d'API, suffisante pour les cas simples, est disponible.

Aller plus loin

Avec API Platform, il est aisé de personnaliser les opérations et les éléments à faire apparaitre.

Personnaliser les propriétés renvoyées

Grâce à des annotations / attributs, il est possible de préciser quelles propriétés (dé)sérialiser. On peut se greffer au système de normalisation ou de dé-normalisation de Symfony, grâce à des annotations et aux paramètres de l'annotation ApiResource :

<?php
// api/src/Entity/Test.php

namespace App\Entity;

use ApiPlatform\Metadata\ApiResource;
use Symfony\Component\Serializer\Annotation\Groups;

#[ApiResource(
    normalizationContext: ['groups' => ['read']],
    denormalizationContext: ['groups' => ['write']],
)]
class Test 
{
    #[Groups(["read", "write"])]
    protected string $property = "";
    
    #[Groups(["read"])]
    protected string $property2 = "";
    // ...
}

Dans l'exemple ci-dessus, la propriété property sera utilisable à la fois dans le contexte de normalisation (lecture avec GET d'un élément ou d'une collection) ou de dé-normalisation (écriture avec PUT, POST ou PATCH). La propriété property2 ne sera utilisable que lors d'une normalisation (lecture avec GET d'un élément ou d'une collection).

Vous pouvez également aller plus loin, en précisant les groupes de (dé)normalisation pour chaque opération (opération sur les items ou les collections, directement sur une opération GET d'un item ou d'une collection, etc.) :

<?php
// api/src/Entity/Test.php

namespace App\Entity;

use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\Put;
use Symfony\Component\Serializer\Annotation\Groups;

#[ApiResource(
    normalizationContext: ['groups' => ['read']],
    denormalizationContext: ['groups' => ['write']],
    operations: [
        new Get(),
        new Put(denormalizationContext: ['groups' => ['put']]),
        new GetCollection(normalizationContext: ['groups' => ['read:collection']]),
    ],
)]
class Test 
{
    #[Groups(["read", "write", "put"])]
    protected string $property = "";
    
    #[Groups(["read", "read:collection"])]
    protected string $property2 = "";
    // ...
}

Dans cet exemple, on définit quelles opérations sont disponibles et quels groupes sont appelés pour (dé)normaliser. Seules les opérations GET et PUT (routes GET /api/tests/{id} et PUT /api/tests/{id}) pour les items sont disponibles et l'opération GET (route GET /api/tests) sur les collections.

⚠️ Noter que :

  • Les opérations sur les items et les collections sont séparées et peuvent être personnalisées / désactivées
  • Les groupes peuvent permettre de personnaliser finement les éléments utilisables dans les différentes routes
  • Il est important de définir un nommage cohérent pour les groupes, pour éviter des soucis (⚠️ dans l'exemple ci-dessus, le nommage des groupes est à re-penser !)

Une idée de nommage (venue des vidéos de Grafikart) serait de nommer les groupes sous la forme opération:Objet:type où :

  • opération est le nom de l'opération liée au groupe : read, write, get, put, etc.
  • Objet est le nom court de la classe (dans mon exemple Test)
  • type est le type d'opération : item ou collection

Validation des données

Lors de l'insertion ou la modification de nos données, il est courant de confirmer leur validité. Le faire dans une API ne change pas cette règle et plusieurs outils sont à notre disposition pour cela.

Nous pouvons déjà utiliser la validation de Symfony sur les différentes propriétés. API Platform pourra alors utiliser cette validation pour afficher les messages d'erreur, le cas échéant.

Cependant, il est possible d'aller plus loin et de définir des groupes de validation pour l'api, ou même définir des groupes de validation par opération !

Comme nous resterons à des bases dans ce cours, je vous laisserai voir les documentations ci-dessus pour des exemples plus détaillés.

Dernières mise à jour :
Prev
Easy Admin Bundle
Next
Pense-bêtes