def. d’une API

API : Application Programming Interface


API REST


Raisons et Intérêts des API

OCR : construire une API REST : Communication entre plusieurs applications
OCR : construire une API REST : Communication entre plusieurs applications

les API(s) sont partout !


consommer une API : exemple sur cosycosy

consommer une API


curl 'https://geo.api.gouv.fr/regions'
curl 'https://geo.api.gouv.fr/regions/27'
    => réponse :    `{"nom":"Bourgogne-Franche-Comté","code":"27"}`
curl 'https://geo.api.gouv.fr/regions?nom=Bourgogne'
curl 'https://geo.api.gouv.fr/regions?nom=Hauts-de-France'

Consommer une API : c’est faire un programme “client” qui exécute une requête HTTP sur une API (un site web …) pour récupérer (ou ajouter/modifier/supprimer) des informations.

les contraintes de l’architecture REST

REST (RESTfull) : Ce n’est pas un protocole mais une façon de s’organiser(règles, charte de bonne conduite pour mettre à disposition des informations).

Architecture REST : Representation State Transfert

6 contraintes :

  1. Architecture client/serveur : c’est le cas du protocole HTTP
  2. Stateless (sans état) : on ne conserve pas de contexte entre les requêtes donc pas de variable de session par exemple. L’utilisateur doit donc être authentifié à chaque requête !
  3. cacheable : on doit pouvoir mettre en cache la ressource pour s’en resservir pour des requêtes similaires consécutives
  4. latered system (système scindé en couche) : le client n’a pas à savoir comment générer la ressource
  5. Uniform Interface : contrainte au niveau de la ressource qui doit :
  6. facultative : Code on Demand (non abordé)


Certains articles proposent plus de 6 contraintes

exemple : consommer l’API geo



Modifier le controleur ConsommerGeoController


Ancienne méthode avec file_get_content : Ajouter le code ci-dessous dans la méthode listeRegions

        // https://www.php.net/manual/fr/function.file-get-contents.php
        $mesRegions=file_get_contents("https://geo.api.gouv.fr/regions");
        dump($mesRegions);

        return $this->render('api1geo/listeRegion.html.twig', [
            'mesRegions' => $mesRegions
        ]);

decoder du json avec le serializer

        // etape 1 : decoder
        $mesRegionsTab=$serializer->decode($mesRegions,'json');
        dd($mesRegionsTab);    // remplacer dd par dump

Documentation symfony du serializer


TWIG (la vue) n’est pas capable d’afficher du json : il faut transformer le JSON en tableau associatif avant d’appeler la vue pour l’afficher.

“dénormaliser”

Utiliser l’entité Region (classe PHP sans annotation de l’ORM Doctrine pour ne pas être mappée dans la BDD)

// etape 2 : denormalizer
$mesRegionsObjet=$serializer->denormalize($mesRegionsTab,'App\Entity\Region[]');
dd($mesRegionsObjet);  // remplacer dd par dump

“déserialiser”

// etape 3 : deserializer
$mesRegionsObjet = $serializer->deserialize($mesRegions,'App\Entity\Region[]', 'json' );
dd($mesRegionsObjet);   // remplacer dd par dump

Passer le tableau d’objets ou le tableau de tableaux associatifs à la vue, twig ne fait pas la différence, il s’utilise de la même manière pour afficher un tableau d’objets ou un tableau associatif.

return $this->render('api1geo/listeRegion.html.twig', [
            'mesRegions' => $mesRegionsObjet
        ]);

être plus propre sur la requête HTTP

Il existe plusieurs façons de faire avec des requêtes HTTP en PHP


Tester avec un objet du frameWork symfony très récent http_client, remplacer la fonction file_get_contents par l’objet htt_client.

use Symfony\Contracts\HttpClient\HttpClientInterface;

.....

private $client;

public function __construct(HttpClientInterface $client)
{
    $this->client = $client;
}
$mesRegions=file_get_contents("https://geo.api.gouv.fr/regions");

par

        $response = $this->client->request('GET', 'https://geo.api.gouv.fr/regions');

        $statusCode = $response->getStatusCode();
// $statusCode = 200
        dump($statusCode);
        $contentType = $response->getHeaders()['content-type'][0];
        dump($contentType);
// $contentType = 'application/json'
        $content = $response->getContent();
        dump($content);
// $content = '{"id":521583, "name":"symfony-docs", ...}'
        $content2 = $response->toArray();
        dump($content2);
// $content = ['id' => 521583, 'name' => 'symfony-docs', ...]
        dd('fin');
$mesRegionsTab=$this->client->request('GET', 'https://geo.api.gouv.fr/regions')->toArray();

exercice :

<a primary href="{{ path('listeDeptsParRegion') }}?region={{ maRegion.code }}"><p style="color: #0000cc">{{ maRegion.code }}</p></a>
    /**
     * @Route("/listeDeptsParRegion", name="listeDeptsParRegion")
     */
    public function listeDeptsParRegion(Request $request,SerializerInterface $serializer, HttpClientInterface $httpClient)
    {
        $codeRegion=$request->query->get('region');

        $mesDepsTab=[];
        $$mesRegionsTab=[];


        return $this->render('api1geo/listeDeptParRegion.html.twig', [
            'mesRegions' => $mesRegionsTab,
            'mesDepts' => $mesDepsTab
        ]);

    }


        if($codeRegion==null || $codeRegion == "Toutes"){
            // recherche des départements  avec une requête HTTP sur 'https://geo.api.gouv.fr/departements'
        } else {
            // recherche des départements  avec une requête HTTP sur  "https://geo.api.gouv.fr/regions/".$codeRegion."/departements"
        }
        if($ReponseMesDeps->getStatusCode() == 200)
            $mesDepsTab=$ReponseMesDeps->toArray();
        else
            $mesDepsTab=[];

https://symfony.com/doc/current/components/http_client.html

exemple d’une autre API

Documentation de l’API Github

authentification

les API consommées par des services WEB ou sites WEB utilisent généralement OAuth2

https://zestedesavoir.com/articles/1616/comprendre-oauth-2-0-par-lexemple/
http://www.bubblecode.net/fr/2016/01/22/comprendre-oauth2/


Entre VueJs(application Front) et une API, le protocole souvent utilisé est JWT

exercice

Créer une troisième méthode listeCommunesParDpt qui utilise la vue pour afficher toutes les communes d’un département.