API REST ( http://bit.ly/2mQ6BNB )
Initialiser une API Rest, avec la ressource /api/tweets
.
Les méthodes suivantes seront implémentés :
cget()
: retourne la liste de tous les tweetsget($id)
: retourne un tweet par son IDpost()
: création d'un Tweet
De nombreux bundles existent, nous utiliserons ici FOS Rest Bundle
.
Liens:
- FOSREstBundle: http://symfony.com/doc/current/bundles/FOSRestBundle/index.html
- Blog Post API: http://afsy.fr/avent/2013/06-best-practices-pour-vos-apis-rest-http-avec-symfony2
- Doc API: https://github.com/nelmio/NelmioApiDocBundle/blob/master/Resources/doc/index.rst
$ composer require friendsofsymfony/rest-bundle
Et ajouter dans app/AppKernel.php
:
$bundles = array(
// ...
new FOS\RestBundle\FOSRestBundle(),
);
Activer le serializer de Symfony:
# app/config/config.yml
framework:
serializer: { enable_annotations: true }
Et la configuration du bundle :
# app/config/config.yml
fos_rest:
body_listener: true
param_fetcher_listener: true
view:
view_response_listener: 'force'
empty_content: 204
formats:
json : true
format_listener:
enabled: true
rules:
- { path: '^/api', priorities: ['json'], fallback_format: json, prefer_extension: false }
- { path: '^/', stop: true }
Création de notre controller API :
<?php
namespace AppBundle\Controller\Api;
use AppBundle\Entity\Tweet;
use AppBundle\Form\Type\TweetType;
use FOS\RestBundle\Controller\Annotations as FOSRest;
use FOS\RestBundle\Controller\FOSRestController;
use FOS\RestBundle\View\View;
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
use Symfony\Component\HttpFoundation\Response;
/**
* TweetController.
*
* @FOSRest\Route(path="/api/tweets")
*/
class TweetController extends FOSRestController
{
/**
* @FOSRest\View()
* @FOSRest\Get("/")
*
* @ApiDoc(
* section="Tweets",
* description="Returns a collection of Tweets"
* )
*
* @return Tweet[]
*/
public function cgetAction()
{
return $this->getTweetManager()->all();
}
/**
* @FOSRest\View()
* @FOSRest\Get("/{id}")
*
* @ApiDoc(
* section="Tweets",
* description="Get a Tweet",
* output="AppBundle\Entity\Tweet"
* )
*
* @return Tweet
*/
public function getAction(Tweet $tweet)
{
return $tweet;
}
/**
* @FOSRest\Post("/")
* @FOSRest\View(statusCode=201)
*
* @ApiDoc(
* section="Tweets",
* description="Create a new Tweet",
* input="AppBundle\Form\Type\TweetType",
* output="AppBundle\Entity\Tweet"
* )
*
* @param Request $request
*
* @return Form|Tweet
*/
public function postAction(Request $request)
{
$form = $this->get('form.factory')->createNamed('', TweetType::class, $this->getTweetManager()->create(), [
'csrf_protection' => false,
]);
$form->submit($request->request->all());
if ($form->isSubmitted() && $form->isValid()) {
$this->getTweetManager()->save($form->getData());
return $form->getData();
}
return new View($form, Response::HTTP_BAD_REQUEST);
}
/**
* @return \AppBundle\Manager\TweetManager
*/
private function getTweetManager()
{
return $this->get('app.tweet_manager');
}
}
Créons un serializer pour notre classe Tweet :
services:
app.normalizer.tweet:
class: AppBundle\Serializer\Normalizer\TweetNormalizer
tags:
- { name: serializer.normalizer }
<?php
namespace AppBundle\Serializer\Normalizer;
use AppBundle\Entity\Tweet;
/**
* TweetNormalizer.
*/
class TweetNormalizer extends AbstractNormalizer
{
/**
* {@inheritdoc}
*/
public function normalize($object, $format = null, array $context = [])
{
/* @var User $object */
return [
'id' => $object->getId(),
'message' => $object->getMessage(),
'createdAt' => $object->getCreatedAt()->format('d/m/Y H:i:s'),
'isEnabled' => $object->isEnabled(),
];
}
/**
* {@inheritdoc}
*/
public function supportsNormalization($data, $format = null)
{
return $data instanceof Tweet;
}
}