API Livres/Auteurs¶
Pour fabriquer une API nous pouvons le faire :
à la Main
avec APIPlatform
API livres et auteurs « à la main »¶
Avant de commencer nous allons installer le bundle nelmio/cors-bundle :
composer req cors
ou
composer require nelmio/cors-bundle
L’installation se lance.
Using version ^2.0 for nelmio/cors-bundle
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Restricting packages listed in "symfony/symfony" to "5.0.*"
Package operations: 1 install, 0 updates, 0 removals
- Installing nelmio/cors-bundle (2.0.1): Downloading (100%)
Writing lock file
Generating autoload files
ocramius/package-versions: Generating version class...
ocramius/package-versions: ...done generating version class
Symfony operations: 1 recipe (b3d83b533e25e4f0b71e3e2b85c51c5d)
- Configuring nelmio/cors-bundle (>=1.5): From github.com/symfony/recipes:master
Executing script cache:clear [OK]
Executing script assets:install public [OK]
Some files may have been created or updated to configure your new packages.
Please review, edit and commit them: these files are yours.
Le cors-bundle permet de définir les règles CORS. Ce bundle permet également de définir les domaines qui auront accès à votre API REST.
Vérifions que les règles ont bien été définies dans /config/packages/nelmio_cors.yaml
nelmio_cors:
defaults:
origin_regex: true
allow_origin: ['%env(CORS_ALLOW_ORIGIN)%']
allow_methods: ['GET', 'OPTIONS', 'POST', 'PUT', 'PATCH', 'DELETE']
allow_headers: ['Content-Type', 'Authorization']
expose_headers: ['Link']
max_age: 3600
paths:
'^/': null
Dans .env modifions le paramètre d’autorisation des domaines.
###> nelmio/cors-bundle ###
CORS_ALLOW_ORIGIN=*
###< nelmio/cors-bundle ###
Ce paramètre permet à n’importe quel domaine d’accéder à notre API. /!A n’utiliser que pour des APIs puliques /!
Ajoutons un controleur d’Auteur et un autre de Livre avec :
php bin/console make:controller AuteurController --no-template
php bin/console make:controller LivreController --no-template
On obtient déjà par exemple pour AuteurController
un index qui renvoie un contenu json :
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
class AuteurController extends AbstractController
{
/**
* @Route("/auteur", name="auteur")
*/
public function index()
{
return $this->json([
'message' => 'Welcome to your new controller!',
'path' => 'src/Controller/AuteurController.php',
]);
}
}
Lister tous les auteurs¶
Complétons AuteurController
:
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use App\Entity\Auteur;
/**
* @Route("/books/api/v1.0")
*/
class AuteurController extends AbstractController
{
/**
* Permet d'avoir la liste de tous les auteurs
* @Route("/auteur", name="liste_auteur", methods={"GET"})
*/
public function listeAuteur()
{
$repository = $this->getDoctrine()->getRepository(Auteur::class);
$listeAuteur = $repository->findAll();
$listeReponse = array();
foreach ($listeAuteur as $auteur) {
$listeReponse[] = array(
'id' => $auteur->getId(),
'nom' => $auteur->getNom(),
'prenom' => $auteur->getPrenom(),
);
}
$reponse = new Response();
$reponse->setContent(json_encode(array("auteur"=>$listeReponse)));
$reponse->headers->set("Content-Type", "application/json");
$reponse->headers->set("Access-Control-Allow-Origin", "*");
return $reponse;
}
Puis pour avoir les détails d’un auteur¶
<?php
/**
* Permet d'avoir les livre d'un auteur grâce à son id
* @Route("/auteur/{id}", name="details_auteur", methods={"GET"})
*/
public function detailsAuteur($id)
{
$repository = $this->getDoctrine()->getRepository(Auteur::class);
$auteur = $repository->find($id);
$listeLivre = $auteur->getLivres();
$livres = [];
foreach ($listeLivre as $livre) {
$livres[] = array(
"id" => $livre->getId(),
"titre" => $livre->getTitre(),
);
}
$reponse = new Response(json_encode(array(
'id' => $auteur->getId(),
'nom' => $auteur->getNom(),
'prenom' => $auteur->getPrenom(),
'livres' => $livres,
))
);
$reponse->headers->set("Content-Type", "application/json");
$reponse->headers->set("Access-Control-Allow-Origin", "*");
return $reponse;
}
Créer un auteur¶
<?php
/**
* Permet de créer un auteur
* @Route("/auteur", name="nouveau_auteur", methods={"POST"})
*/
public function nouveauAuteur(Request $request)
{
$entityManager = $this->getDoctrine()->getManager();
$auteur = new Auteur();
$body = json_decode($request->getContent(), true);
$nom = $body['nom'];
$prenom = $body['prenom'];
$auteur->setNom($nom);
$auteur->setPrenom($prenom);
$entityManager->persist($auteur);
$entityManager->flush();
$reponse = new Response(json_encode(array(
'id' => $auteur->getId(),
'nom' => $auteur->getNom(),
'prenom' => $auteur->getPrenom()
)
));
$reponse->headers->set("Content-Type", "application/json");
$reponse->headers->set("Access-Control-Allow-Origin", "*");
return $reponse;
}
Supprimer un auteur¶
<?php
/**
* Permet de supprimer un auteur grâce à son id
* @Route("/auteur", name="suppression_auteur", methods={"DELETE"})
*/
public function suppressionAuteur(Request $request)
{
$entityManager = $this->getDoctrine()->getManager();
$repository = $this->getDoctrine()->getRepository(Auteur::class);
$body = json_decode($request->getContent(), true);
$id = $body['id'];
$auteur = $repository->find($id);
$entityManager->remove($auteur);
$entityManager->flush();
$reponse = new Response(json_encode(array(
'nom' => $auteur->getNom(),
'prenom' => $auteur->getPrenom(),
))
);
$reponse->headers->set("Content-Type", "application/json");
$reponse->headers->set("Access-Control-Allow-Origin", "*");
return $reponse;
}
Modifier un auteur¶
<?php
/**
* Permet de modifier le nom et/ou le prenom d'un auteur grâce à son id
* La gestion des livres de l'auteur se fera via l'entité livre
* @Route("/auteur", name="modification_auteur", methods={"PUT"})
*/
public function modificationAuteur(Request $request)
{
$entityManager = $this->getDoctrine()->getManager();
$repository = $this->getDoctrine()->getRepository(Auteur::class);
$body = json_decode($request->getContent(), true);
$id = $body['id'];
$nom = $body['nom'];
$prenom = $body['prenom'];
$auteur = $repository->find($id);
$auteur->setNom($nom);
$auteur->setPrenom($prenom);
$entityManager->persist($auteur);
$entityManager->flush();
$reponse = new Response(json_encode(array(
'id' => $auteur->getId(),
'nom' => $auteur->getNom(),
'prenom' => $auteur->getPrenom(),
))
);
$reponse->headers->set("Content-Type", "application/json");
$reponse->headers->set("Access-Control-Allow-Origin", "*");
return $reponse;
}
L’API/CRUD de l’entité Auteur est terminée. Faites les mêmes manipulations pour l’entité Livre : lister tous les livres, détails d’un livre, créer un livre, supprimer un livre et modifier un livre. N’oubliez pas le livre stock l’auteur.
Notre API est complète mais nous avons du travailler dur … Nous aurions pu prendre une solution de facilité !
Avec le composant d’API APIPlatform¶
Installation d’APIPlatform¶
On l’installe avec la recette flex correspondante :
composer req api
Annotons les entités Auteur
et Livres
en ajoutant l’import :
<?php
use ApiPlatform\Core\Annotation\ApiResource;
et l’annotation:
/**
* @ApiResource()
*/
Voilà !
Visitons la page : API
Notre API est prête à l’emploi :

GraphQL¶
GraphQL permet de faire des requêtes plus complexes sur une API et permet donc d’interopérer de façon plus complète avec cette API. Voir GraphQL .
Pour activer le support GraphQL dans Symfony :
composer require webonyx/graphql-php,
Puis visiter : /api/graphql
Consultez la documentation d”APIPlatform
FriendsOfSymfony REST Bundle¶
Une autre solution pour fabriquer un service REST est de passer par un autre Bundle connu : FOS (Friends Of Symfony). On installe le Bundle REST correspondant avec:
composer require friendsofsymfony/rest-bundle
Un exemple complet se trouve sur : Symfony5ApiRest