Tous droits réservés

Créez une API REST avec Symfony 3

Tout au long de ce cours, nous allons apprendre à mettre en œuvre les principes de REST pour concevoir et développer une API web avec Symfony 3.

REST s’est imposé dans le monde du web comme étant un paradigme approuvé et éprouvé pour concevoir des APIs (Application Programming Interface).

De grandes entreprises comme Github, Facebook (Graph) ou YouTube l’utilisent pour fournir des APIs largement utilisées pour accéder à leurs services.

À l’ère des sites web en Single Page Applications et des applications mobiles (Android, IOS ou encore Windows Phone), savoir développer une API est devenu incontournable.

Pourquoi utiliser REST plutôt qu’une autre technologie ou architecture ? Quels avantages cela peut-il nous apporter ? Comment développer une API REST avec Symfony ?

Tout au long de ce cours, nous allons apprendre à mettre en œuvre les principes de REST pour développer rapidement une application web fiable et extensible avec le framework Symfony et l’un de ses bundles phares FOSRestBundle.

Un tour d'horizon des concepts REST

  1. REST en quelques mots
  2. Pourquoi utiliser REST

Développement de l'API REST

  1. Notre environnement de développement

    1. Environnement technique

    2. Création d'un projet Symfony

  2. Premières interactions avec les ressources

    1. Lire une collection

    2. Lire une ressource

    3. Les codes de statut (status code) pour des messages plus expressifs

  3. FOSRestBundle et Symfony à la rescousse

    1. Installation de FOSRestBundle

    2. Routage avec FOSRestBundle

    3. Quid de l'attribut _format ?

    4. Gestion des réponses avec FOSRestBundle

    5. Pratiquons avec notre code

  4. Créer et supprimer des ressources

    1. Création d'une ressource

    2. Suppression d'une ressource

  5. Mettre à jour des ressources

    1. Mise à jour complète d'une ressource

    2. Mise à jour partielle d'une ressource

    3. Notre application vu selon le modèle de Richardson

  6. Relations entre ressources

    1. Hiérarchie entre ressources : la notion de sous-ressources

    2. Les groupes avec le sérialiseur de Symfony

    3. Mise à jour de la suppression d'une ressource

  7. TP : Le clou du spectacle - Proposer des suggestions aux utilisateurs

    1. Énoncé

    2. Détails de l'implémentation

    3. Travail préparatoire

    4. Proposer des suggestions aux utilisateurs

  8. REST à son paroxysme

    1. Supporter plusieurs formats de requêtes et de réponses

    2. L'Hypermédia

Amélioration de l'API REST

  1. Sécurisation de l'API 1/2

    1. Connexion et déconnexion avec une API

    2. Login et mot de passe pour les utilisateurs

    3. Création d'un token

  2. Sécurisation de l'API 2/2

    1. Exploitons le token grâce à Symfony

    2. Gestion des erreurs avec FOSRestBundle

    3. 401 ou 403, quand faut-il utiliser ces codes de statut ?

    4. Suppression d'un token ou la déconnexion

  3. Créer une ressource avec des relations

    1. Rappel de l'existant

    2. Création d'un lieu avec des tarifs

    3. Bonus : Une validation plus stricte

  4. Quand utiliser les query strings ?

    1. Pourquoi utiliser les query strings ?

    2. Gestion des query strings avec FOSRestBundle

    3. Paginer et Trier les réponses

  5. JMSSerializer : Une alternative au sérialiseur natif de Symfony

    1. Pourquoi utiliser JMSSerializerBundle ?

    2. Installation et configuration de JMSSerializerBundle

    3. Impact sur l'existant

  6. La documentation avec OpenAPI (Swagger RESTFul API)

    1. Qu'est-ce que OpenAPI ?

    2. Rédaction de la documentation

    3. Installer et utiliser Swagger UI

  7. Automatiser la documentation avec NelmioApiDocBundle

    1. Installation de NelmioApiDocBundle

    2. L'annotation ApiDoc

    3. Étendre NelmioApiDocBundle

    4. Le bac à sable

    5. Générer une documentation compatible OpenAPI

  8. FAQ

    1. Comment générer des pages HTML depuis l'application Symfony 3 ?

    2. Comment autoriser l'accès à certaines urls avec notre système de sécurité ?



Nous avons pu voir tout au long de ce cours que les contraintes REST permettent de mettre en place une API uniforme et facile à prendre en main. La mise en œuvre de ces contraintes offre un ensemble d’avantages et le framework Symfony dispose d’outils suffisamment matures pour aider dans les développements.

Ce cours bien qu’étant assez long n’aborde pas tous les concepts de REST ni toutes les fonctionnalités qu’apportent FOSRestBundle et les différents bundles utilisés. Son objectif est de présenter de manière succincte l’essentiel des notions à comprendre pour pouvoir développer une API RESTFul et l’améliorer en toute autonomie.

Le style d’architecture REST ne s’occupe pas des détails d’implémentations mais plutôt du rôle de chaque composant de notre application.

N’hésitez surtout pas enrichir l’API et à explorer les documentations officielles des différents outils abordés pour mieux cerner tout ce qu’ils peuvent vous apporter.

91 commentaires

A la lecture de l'intro, de la conclusion et du plan, le tutoriel promet d'être très enrichissant pour les membres et s'il est bon (ce dont je ne doute pas !), il a le potentiel de devenir un incontournable sur Zeste de Savoir.

Bravo pour ce tutoriel !

Un chapitre sur Open API (anciennement Swagger RESTful API) et un sur NelmioApiDocBundle sont déjà rédigés mais pas encore uploadés sur ZdS.

Par contre pour OAuth2 après pas mal de réflexion, j'ai décidé de ne pas en parler parce que je considère que avant d'utiliser FOSOAuthServerBundle, il faut une bonne connaissance de OAuth. Ce qui me parait un peu hors scope (peut être dans un cours à part pour bien présenter OAuth2 avant de parler de FOSOAuthServerBundle).

Salut. Déjà je dirais merci pour cet excellent tutoriel. Quelques remarques si je puis me permettre (elles ne concernent que le chapitre FOSRestBundle et Symfony à la rescousse

  1. Quand on renvoie directement les lieux(ou le lieu), on a clairement un resultat mais il est vide, dont les getters ne sont pas appelés automatiquement
  2. Je trouve dommage que nous n'utilisions pas les fixtures pour polluer notre bdd (je sais c'est pas important, mais je trouve cela plus pratique vu que nous sommes sur Symfony)

Mais sinon, pour ce que j'ai lu, c'est déjà bien plus que ce j'aurais espérer et t'en remercie encroe. Je continue mon aventure. Courage

+0 -0

Salut,

Merci pour ton retour.

Quand on renvoie directement les lieux(ou le lieu), on a clairement un resultat mais il est vide, dont les getters ne sont pas appelés automatiquement.

Je t’invite à revoir ta configuration ou à créer le cas échéant un sujet sur le forum pour qu’on puisse résoudre ce problème. Tout le reste du tutoriel se base sur ce principe. Il est donc primordial que cela fonctionne correctement.

Je trouve dommage que nous n’utilisions pas les fixtures pour polluer notre bdd (je sais c’est pas important, mais je trouve cela plus pratique vu que nous sommes sur Symfony).

Si tu es suffisamment à l’aise avec les fixtures, tu peux les implémenter pour te faciliter le travail. (D’ailleurs, je les utilise pour tester fonctionnellement l’API avec behat :-° ). L’objectif visé ici est de laisser le lecteur se focaliser sur le développement de son API sans avoir à apprendre des sujets annexes.

Salut,

Salut,

Merci pour ton retour.

Quand on renvoie directement les lieux(ou le lieu), on a clairement un resultat mais il est vide, dont les getters ne sont pas appelés automatiquement.

Je t'invite à revoir ta configuration ou à créer le cas échéant un sujet sur le forum pour qu'on puisse résoudre ce problème. Tout le reste du tutoriel se base sur ce principe. Il est donc primordial que cela fonctionne correctement.

BestCoder

Evidemment je me retrouve un peu coincé plus loin dans le tutoriel et sans mentir je ne veux pas faire des formatages à chaque évolution/changement des entités. Du coup je me demande de quelle configuration tu fais allusion, vu que j'ai suivi chaque partie de ce tutoriel depuis l'installation de Symfony(j'avoue que pour cette dernière je suis passé par composer car problème avec l'installateur).

Je trouve dommage que nous n'utilisions pas les fixtures pour polluer notre bdd (je sais c'est pas important, mais je trouve cela plus pratique vu que nous sommes sur Symfony).

Si tu es suffisamment à l'aise avec les fixtures, tu peux les implémenter pour te faciliter le travail. (D'ailleurs, je les utilise pour tester fonctionnellement l'API avec behat :-° ). L'objectif visait ici est de laisser le lecteur se focaliser sur le développement de son API sans avoir à apprendre des sujets annexes.

BestCoder

T'inquiète je comprends bien évidemment ta raison, ce n'était qu'une proposition (pas importante) ;)

+0 -0

Désolé d'avoir pollué le sujet, mais au fur et à mesure que j’avançais dans la lecture, j'ai trouvé une solution plutôt intéressante: la sérialisation et les groupes. Je l'ai mis en place sur toutes les entités en suivant le lien que tu as fourni.

Merci à toi pour ce cours et ta patience.

+1 -0

Une petite remarque que j'ai oublié de notifier depuis, pourquoi lier la propriété $user à préférences dans l'entité AuthToken?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity()
 * @ORM\Table(name="auth_tokens",
 *      uniqueConstraints={@ORM\UniqueConstraint(name="auth_tokens_value_unique", columns={"value"})}
 * )
 */
class AuthToken
{
    //.....
    /**
     * @ORM\ManyToOne(targetEntity="User", inversedBy="preferences") // <---- ici
     * @var User
     */
    protected $user;

    //....
}
+0 -0

Woaw quelle MaJ

Un tout grand merci pour le chapitre sur NelmioApiDocBundle, je trouvais justement que ma doc avait plein de petit soucis mais j'avais pas le temps de fouiller le web pour savoir comment gérer l'affichage des erreurs ou bêtement les collections d'éléments.

Bref, je vais pouvoir parfaire mon API :) Merci !

+1 -0

Voici les derniers chapitres qui clôturent ce tutoriel ! J’espère que c'est le premier d'une longue série de cours.

Un grand merci à tcit qui a pris le temps de valider ces 16 chapitres avec des retours avisés et pertinents.

@azeupaul tu peux maintenant t'amuser avec. :lol:

@La source le chapitre "Créer une ressource avec des relations" est pour toi. Je l'ai créé suite à une de tes questions durant la béta.

Mon regard a été attiré par la documentation j'avais zappé le chapitre :honte:

Excellent ! :)

Petite remarque à propos de la méthode postPlacesAction, il n'est pas nécessaire d'écrire le code parcourant le tableau des éléments, il suffit dans l'entité Place pour l'attribut prices mettre un cascade={"persist"} dans l'annotation doctrine, de disposer d'une méthode addPrice et removePrice et Symfony s'occupe du reste pour complèter et persister l'entité.

Dans la méthode addPrice on écris quelque chose du style:

1
2
3
4
5
6
7
8
<?php

public function addPrice(Price $price) {
    if ( !$this->prices->contains($price) ) {
        $this->prices->add($price);
        $price->setPlace($this);
    }
}
+0 -0

Tu peux effectivement faire cela mais … Tu utilises cascade={"persist"}, Méfie toi de cascade de Doctrine, cela peut te jouer des tours. :diable:

However, pulling objects graph into memory on cascade can cause considerable performance overhead, especially when cascading collections are large. Makes sure to weigh the benefits and downsides of each cascade operation that you define.

http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/working-with-associations.html#transitive-persistence-cascade-operations

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte