5. Une première entité

Notre première entité 

Créons maintenant notre première entité. Ce sera une entité Phone, avec les propriétés suivantes : name, price, color et description.

Libre à vous de créer l'entité que vous souhaitez, avec les caractéristiques associées.

Placez-vous dans votre terminal et lancer la commande suivante : 

./bin/console make:entity

Voici les caractéristiques de nos champs : 

- le champ name sera de type string, avec une limite de 255 caractères ;

- le champ price sera de type integer ;

- le champ color sera de type string avec une longueur de 255 caractères ;

- le champ description sera de type text.

Et voici notre entité générée : 

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="App\Repository\PhoneRepository")
 */
class Phone
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $name;

    /**
     * @ORM\Column(type="integer")
     */
    private $price;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $color;

    /**
     * @ORM\Column(type="text")
     */
    private $description;

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getName(): ?string
    {
        return $this->name;
    }

    public function setName(string $name): self
    {
        $this->name = $name;

        return $this;
    }

    public function getPrice(): ?int
    {
        return $this->price;
    }

    public function setPrice(int $price): self
    {
        $this->price = $price;

        return $this;
    }

    public function getColor(): ?string
    {
        return $this->color;
    }

    public function setColor(string $color): self
    {
        $this->color = $color;

        return $this;
    }

    public function getDescription(): ?string
    {
        return $this->description;
    }

    public function setDescription(string $description): self
    {
        $this->description = $description;

        return $this;
    }
}

 

Mettons à jour la base de données

Comme indiqué à la fin de la génération de notre entité, lancez la commande :

./bin/console make:migration

 Cette commande va générer un fichier de migration de la base de données.

Lancez maintenant la commande :

./bin/console doctrine:migrations:migrate

Cette commande va regarder s'il y a des nouveaux fichiers de migrations, et mettre à jour la base de données en conséquence.

Occupons-nous maintenant de faire appel à notre entité dans notre API 😉

Mais avant, faisons une petite parenthèse pour parler du Serializer de Symfony.

 

Le serializer de Symfony

Pour en savoir plus concernant le fonctionnement de ce composant, vous pouvez regarder la vidéo du composant Serializer

Mettez-vous dans votre terminal et lancez la commande :

composer require serializer

 

Récupérons notre entité au format JSON

Maintenant que notre composant est installé, créons une première entité et faisons appel à notre composant pour transformer notre entité en JSON : 

<?php

namespace App\Controller;

use App\Entity\Phone;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Serializer\SerializerInterface;

class ApiController extends AbstractController
{
    /**
     * @Route("/api", name="api")
     */
    public function index(SerializerInterface $serializer)
    {
        $phone = new Phone();
        $phone->setName('iPhone X');
        $phone->setPrice(1000);
        $phone->setColor('Noir');
        $phone->setDescription('Un superbe iphone');

        $data = $serializer->serialize($phone, 'json');

        return new JsonResponse($data);
    }
}

Retournez sur Postman et actualisez votre requête : 😱😱😱


 

C'est quoi cette réponse en JSON affreuse ? 😒

Effectivement, il y a un problème, mais d'où vient-il ? Si vous regardez bien votre code, vous allez comprendre ce qui se passe. 

Euh, je t'ai pas suivi là 😔

Ok, je vous explique. Ce qui s'est passé à la différence de tout à l'heure, c'est qu'on avait envoyé précédemment un tableau dans notre JsonResponse, et Symfony a transformé ce tableau en JSON.

Ici, c'est un peu différent, on a passé un objet au Serializer de Symfony, en lui demandant de transformer cet objet au format JSON.

Ce que tu est en train de nous dire, c'est que $data est déjà du JSON ?

Exactement. Du coup, on n'a plus besoin de renvoyer une JsonReponse, une Response suffit 😉

Modifiez votre code en renvoyant une Response (du composant HttpFoundation) : 

<?php

namespace App\Controller;

use App\Entity\Phone;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Serializer\SerializerInterface;

class ApiController extends AbstractController
{
    /**
     * @Route("/api", name="api")
     */
    public function index(SerializerInterface $serializer)
    {
        $phone = new Phone();
        $phone->setName('iPhone X');
        $phone->setPrice(1000);
        $phone->setColor('Noir');
        $phone->setDescription('Un superbe iphone');

        $data = $serializer->serialize($phone, 'json');

        return new Response($data);
    }
}
Pensez à retirer le use correspondant à la JsonResponse.

Retournez sur Postman et actualisez : 

Ah c'est mieux maintenant. Mais on avait pas un affichage "différent" tout à l'heure ?

Effectivement, si vous regardez l'onglet headers dans Postman, vous allez voir ceci : 

Pourquoi le Content-Type a changé ? 

Maintenant qu'on renvoie une Response et non une JsonResponse, le Content-Type par défaut n'est plus de type : application/json

Comment fait-on alors ? 😬

C'est très simple : on va lui dire qu'on veut un format json :

<?php

namespace App\Controller;

use App\Entity\Phone;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Serializer\SerializerInterface;

class ApiController extends AbstractController
{
    /**
     * @Route("/api", name="api")
     */
    public function index(SerializerInterface $serializer)
    {
        $phone = new Phone();
        $phone->setName('iPhone X');
        $phone->setPrice(1000);
        $phone->setColor('Noir');
        $phone->setDescription('Un superbe iphone');

        $data = $serializer->serialize($phone, 'json');

        return new Response($data, 200, [
            'Content-Type' => 'application/json'
        ]);
    }
}

 Si vous retournez sur Postman et que vous actualisez votre requête : 

On retrouve bien notre affichage initial, et côté headers : 

Notre Content-Type est bien de type application/json

Occupons-nous maintenant d'ajouter des fixtures dans notre application.