Index de l'article

Construction d'API

1) Création d'un projet

composer create-project symfony/skeleton mon-API

2) Installer Apache, Annotation, JMS-serializer, Doctrine et Maker

cd mon-API
composer require symfony/apache-pack
composer require annotations
composer require jms/serializer-bundle
composer require symfony/orm-pack
composer require doctrine maker

3) Base de données

Dans .env :

DATABASE_URL=mysql://root:''@127.0.0.1:3306/mon_api
php bin/console doctrine:database:create

4) Entité de test

php bin/console make:entity Article

Avec son 1er champ title, en string, 100 caractères, non-nullable ; et un 2ème champ content, en text, non-nullable.

php bin/console make:migration
php bin/console doctrine:migrations:migrate

5) Le contrôleur

Dans src / Controller créer un fichier de type MonApi.php :

php bin/console make:controller MonApi

Puis dans le fichier MonApiController.php :

<?php

namespace App\Controller;

use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;

use App\Entity\Article;
use Symfony\Component\HttpFoundation\Response;

class MonApiController extends Controller
{
/**
* @Route("/articles/{id}", name="article_show")
*/
public function showAction()
{
$article = new Article();
$article
->setTitle('Mon premier article')
->setContent('Le contenu de mon article.')
;
$data = $this->get('jms_serializer')->serialize($article, 'json');

$response = new Response($data);
$response->headers->set('Content-Type', 'application/json');

return $response;
}
}

L'URL http://localhost/mon-API/public/articles/1 doit renvoyer un json.

6) Postman

Installez l'extension Postman pour Chrome, et testez une requête GET sur l'URL http://localhost/mon-API/public/articles/1.

Postman doit bien renvoyer le même json, tel que décrit dans votre contrôleur, et visible dans un navigateur.

7) Requête Post

Modifions maintenant la classe de notre contrôleur afin d'être capable d'envoyer des données soumises par un cient :

...

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Symfony\Component\HttpFoundation\Request;

...

/**
* @Route("/articles", name="article_create")
* @Method({"POST"})
*/
public function createAction(Request $request)
{
$data = $request->getContent();
$article = $this->get('jms_serializer')->deserialize($data, 'App\Entity\Article', 'json');
$em = $this->getDoctrine()->getManager();
$em->persist($article);
$em->flush();
return new Response('', Response::HTTP_CREATED);
}
...

Maintenant la route http://localhost/mon-API/public/articles attend des données en fonction de l'entité Article, et sous forme de json.

L'URL elle-même ne fonctionne pas telle quelle, mais sous Postman, une requête de type Post avec des données json remplira bien la base de données.

postman 1

8) Méthodes d'affichage

Modifions notre contrôleur afin d'afficher de vrais articles selon l'id ainsi que la liste complète des articles :

<?php

namespace App\Controller;

use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;

use App\Entity\Article;
use Symfony\Component\HttpFoundation\Response;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Symfony\Component\HttpFoundation\Request;

class MonApiController extends Controller
{
/**
* @Route("/articles/{id}", name="article_show")
*/
public function showAction(Article $article)
{
$data = $this->get('jms_serializer')->serialize($article, 'json');

$response = new Response($data);
$response->headers->set('Content-Type', 'application/json');

return $response;
}

/**
* @Route("/articles", name="article_create")
* @Method({"POST"})
*/
public function createAction(Request $request)
{
$data = $request->getContent();
$article = $this->get('jms_serializer')->deserialize($data, 'App\Entity\Article', 'json');

$em = $this->getDoctrine()->getManager();
$em->persist($article);
$em->flush();

return new Response('', Response::HTTP_CREATED);
}

/**
* @Route("/articles_list", name="article_list")
* @Method({"GET"})
*/
public function listAction()
{
$articles = $this->getDoctrine()->getRepository('App:Article')->findAll();
$data = $this->get('jms_serializer')->serialize($articles, 'json');

$response = new Response($data);
$response->headers->set('Content-Type', 'application/json');

return $response;
}
}

9) Cacher des champs

Il faut modifier l'entité pour appeler le Serializer (use JMS\Serializer\Annotation as Serializer;), cacher tous les champs (* @Serializer\ExclusionPolicy("ALL")), puis en appeler certains (* @Serializer\Expose) :

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use JMS\Serializer\Annotation as Serializer;

/**
* @ORM\Entity(repositoryClass="App\Repository\ArticleRepository")
* @Serializer\ExclusionPolicy("ALL")
*/
class Article
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;

/**
* @ORM\Column(type="string", length=100)
* @Serializer\Expose
*/
private $title;

/**
* @ORM\Column(type="text")
* @Serializer\Expose
*/
private $content;
...

xx

xx

xx