Skip to content

API Rest & Symfony : les débuts

SimplonReunion edited this page Jun 29, 2016 · 1 revision

Nous allons mettre en place une min api basique avec Symfony.

La base de l'exercice sera l'exo repo.

Nous ne prendrons pas en compte la gestion des utilisateurs et des droits d'accès.

On va commencer par retourner la liste des clients des gites sous la forme Json.

Jusqu'à maintenant, on retournait une vue : un template twig. Cette vue est ni plus ni moins qu'une réponse de type html. Avec l'api on va renvoyer une réponse de type Json plutôt. C'est le front-end qui s'occupera de la mise en forme en se basant sur ce Json.

Pour tester nos urls nous allons utiliser un système qui permet juste d'envoyer des requêtes HTTP à notre application et d'afficher les réponses sans avoir besoin à développer une interface front-end. Il y a plusieurs façons de le faire. Nous allons opter pour l'extension Chrome Postman, assez simple à utiliser.

Le controller

Lister

Nous allons créer un nouveau controller qu'on appellera RestClientController.php qui se trouvera dans le bundle de RepoPlaygroundBundle.

Dans ce nouveau controller, on va définir une action qui a pour route '/api/clients' et qui va retourner la liste des clients des gites sous format Json. Cette route doit être accessible uniquement par en méthode GET.

Pour récupérer les clients,on peut reprendre ce qu'on a déjà fait. La seule chose qui va changer c'est la fin de l'action. Nous n'allons plus retourner une vue mais plutôt un objet JsonResponse, Symfony\Component\HttpFoundation\JsonResponse pour un être précis.

Ci dessous la fameuse action :

/**
     * Lister tous les clients.
     *
     * @Route("/clients", name="api_clients")
     * @Method("GET")
     */
    public function getClientsAction()
    {
        $em = $this->getDoctrine()->getManager();

        $clients = $em->getRepository('SimplonReunionRepoPlaygroundBundle:Client')->findAll();
        //retourne la réponse Json
        return new JsonResponse(json_encode($clients));
    }

Si on teste, on aura un Json sans données à l'intérieur. C'est parce que JsonResponse ne sait pas convertir des objets en Json.

Nou allons devoir passer par un convertisseur qui va le faire pour nous. l'un des plus utilisés est JMSSerializerBundle. On l'installe en suivant les instructions de la documentation.

On va maintenant modifier notre code pour ajouter le serializer:

/**
     *  Lister tous les clients
     *
     * @Route("/clients", name="api_clients")
     * @Method("GET")
     */
    public function getClientsAction()
    {
        $em = $this->getDoctrine()->getManager();

        $clients = $em->getRepository('SimplonReunionRepoPlaygroundBundle:Client')->findAll();
        //Récupère le serializer (qui est un service)
        $serializer = $this->get('jms_serializer');
        //Converti les objets en Json
        $serializedClients = $serializer->serialize($clients, 'json');

         //retourne la réponse Json
        return new JsonResponse($serializedClients,200,[],true);
    }

Si on regarde la documentation du constructeur de JsonReponse on voit qu'il s'attend à avoir les paramètres suivants :

  • Les données
  • Le statut de la réponse
  • Un tableau pour ajouter des headers
  • Si les données passées sont déjà en Json

Dans notre cas :

  • $serializedClents correspond à nos données à envoyées
  • Tout s'est bien passé donc on veut retourner une réponse qui vaut 200
  • On ne veut pas ajouter des headers supplémentaires donc on passe un tableau vide
  • $serializedClents est déjà en json (merci le serializer) c'est pourquoi le dernier paramètre vaut true

Et voilà maintenant on a la liste des clients sous forme Json.

Exercice

Faites de même pour les autres entités, Gite, Gestionnaire, Reservation, Chambre.

Créer

On sait comment lister des entités avec notre api. On va maintenant voir comment insérer des clients.

Comme pour la partie insertion, on va utiliser le format Json. Les données qui seront passées à notre api seront sous la forme Json :

{
    "nom": "Luke",
    "prenom": "Skywalker",
    "email": "luke@starwars.com"
}

Dans nos actions, nous avons l'habitude de fonctionner avec des forms. Comme les données sont du Json on va utiliser une autre technique pltuôt.

On va créer l'objet Client directement à partir du Json ! On va le déserialisé, puis après une petite validation on va l'insérer dans notre base.

/**
     * Créer un client. IMPORTANT : les données sont soumis sous forme json !
     *
     * @Route("/client", name="api_clients_new")
     * @Method("POST")
     */
    public function newAction(Request $request)
    {
        //Récupère le serializer
        $serializer = $this->get('jms_serializer');
        
        //Les variables sont passées en Json. Il faut alors les transformer en objet Client
        /** @var $client Symfony\Component\Form\Form */
        $client = $serializer->deserialize($request->getContent(),Client::class,'json');
        
        //Faire une validation sur les données fournis par l'utilisateur
        /** @var $validator Symfony\Component\Validator\Validator\ValidatorInterface */
        $validator = $this->get('validator');
        $errors = $validator->validate($client); 
        
        if (count($errors) <= 0) {

            $em = $this->container->get('doctrine')->getManager();
            $em->persist($client);
            $em->flush();

            //Convertir les objets en Json
            $serializedClient = $serializer->serialize($client, 'json');

            return new JsonResponse($serializedClient, 201, [], true);
        }

        return new JsonResponse("Error : form not valid", 400);
    }

Il faut garder à l'esprit que cette façon de faire n'est pas très sécurisée. En effet on est vulnérable a des attaques de type CRSF

Exercice

Créer les actions pour permettre l'ajout des autres entités.

Aller plus loin

Il reste plus qu'à faire la suppression d'un élément et la mise à jour d'un élément. À vous de jouer.