Veuillez patienter...

Créer une api rest avec symfony 3

Bonjour,

En tant que Freelance en développement web, nous avons toujours besoin d'interfacer nos sites avec d'autres. Pour ce faire nous utilisons souvent des API (Applications Programming Interface).

Dans de précédents articles, nous vous expliquions ce qu'est une API et les deux principales méthodes pour les développer en PHP : REST et SOAP.

Nous irons ici plus loin en vous montrant comment créer une API REST en PHP avec le framework Symfony 3 !!!

Pour aller au plus simple, nous supposons que vous ayez un serveur web corrrectement configuré avec Composer installé et fonctionnel.

Pour commencer, il faut installer le framework Symfony :

# A la racine de votre serveur (ou dans le dossier relatif à votre vhost.
composer create-project symfony/framework-standard-edition example "3.3.*"

Cette ligne de commande va servir a télécharger et installer le framework dans le répertoire example.

Ensuite, nous allons utiliser deux bundles essentiels à notre application :

composer require jms/serializer-bundle 
composer require friendsofsymfony/rest-bundle

Il faut créer notre propre bundle :

cd example
php bin/console generate:bundle
php bin/console doctrine:create:database

Nous imaginons mettre à disposition cette entité sur l'API :

# src/ExampleBundle/Resources/config/doctrine/weenesta_user.orm.yml
ExampleBundle\Entity\WeenestaUser:
    type: entity
    table: weenesta_user
    id:
        id:
            type: integer
            generator: { strategy: AUTO }
    fields:
        name:
            type: string
            length: 100

On configure le Bundle pour qu'il utilise le bundle FOS Rest :

#app/config/config.yml
fos_rest:
    format_listener:
        rules:
            - { path: '^/weenestauser', priorities: ['xml', 'json'], fallback_format: xml, prefer_extension: true }
            - { path: '^/', priorities: [ 'text/html', '*/*'], fallback_format: html, prefer_extension: true }

On génère l'entité avec doctrine :

php bin/console doctrine:generate:entity WeenestaUser
php bin/console doctrine:schema:update --force

On créé le controlleur :

#src/ExampleBundle/Controller/WeenestaUserController.php

namespace ExampleBundle\Controller;

use FOS\RestBundle\Controller\FOSRestController;
use Symfony\Component\HttpFoundation\Request;

use FOS\RestBundle\Controller\Annotations\Get;
use FOS\RestBundle\Controller\Annotations\Post;
use FOS\RestBundle\Controller\Annotations\Delete;

use ExampleBundle\Entity\WeenestaUser;

class WeenestaUserController extends FOSRestController
{
    /**
     * findWeenestaUserByRequest
     * 
     * @param Request $request
     * @return WeenestaUser
     * @throws NotFoundException
     */
    private function findWeenestaUserByRequest(Request $request) {

        $id = $request->get('id');
        $user = $this->getDoctrine()->getManager()->getRepository("ExampleBundle:WeenestaUser")->findOneBy(array('id' => $id));

        return $user;
    }

    /**
     * validateAndPersistEntity
     * 
     * @param WeenestaUser $user
     * @param Boolean $delete
     * @return View the view
     */
    private function validateAndPersistEntity(WeenestaUser $user, $delete = false) {

        $template = "ExampleBundle:WeenestaUser:example.html.twig";

        $validator = $this->get('validator');
        $errors_list = $validator->validate($user); 

        if (0 === count($errors_list)) {

            $em = $this->getDoctrine()->getManager();

            if ($delete === true) {
                $em->remove($user);
            } else {
                $em->persist($user);
            }

            $em->flush();

            $view = $this->view($user)
                         ->setTemplateVar('user')
                         ->setTemplate($template);
        } else {

            $errors = "";
            foreach ($errors_list as $error) {
                $errors .= (string) $error->getMessage();  
            }

            $view = $this->view($errors)
                         ->setTemplateVar('errors')
                         ->setTemplate($template);

        } 

        return $view;
    }

    /**
     * newWeenestaUserAction
     * 
     * @Get("/weenestauser/new/{name}")
     * 
     * @param Request $request
     * @return String
     */
    public function newWeenestaUserAction(Request $request)
    {   
        $user = new WeenestaUser();
        $user->setName($request->get('name'));

        $view = $this->validateAndPersistEntity($user);

        return $this->handleView($view);
    }

    /**
     * editWeenestaUserAction
     * 
     * @Get("/weenestauser/edit/{id}/{name}")
     * 
     * @param Request $request
     * @return type
     */
    public function editWeenestaUserAction(Request $request) {

        $user = $this->findWeenestaUserByRequest($request);

        if (! $user) {
            $view = $this->view("No WeenestaUser found for this id:". $request->get('id'), 404);
            return $this->handleView($view);
        }

        $user->setName($request->get('name'));

        $view = $this->validateAndPersistEntity($user);

        return $this->handleView($view);
    }

    /**
     * deleteWeenestaUserAction
     * 
     * @Get("/weenestauser/delete/{id}")
     * 
     * @param Request $request
     * @return type
     */
    public function deleteWeenestaUserAction(Request $request) {

        $user = $this->findWeenestaUserByRequest($request);

        if (! $user) {
            $view = $this->view("No WeenestaUser found for this id:". $request->get('id'), 404);
            return $this->handleView();
        }

        $view = $this->validateAndPersistEntity($user, true);

        return $this->handleView($view);
    }

    /**
     * getWeenestaUserAction
     * 
     * @Get("/sweenestausers")
     * 
     * @param Request $request
     * @return type
     */
    public function getWeenestaUserAction(Request $request) {

        $template = "ExampleBundle:WeenestaUser:example.html.twig";

        $users = $this->getDoctrine()->getManager()->getRepository("ExampleBundle:WeenestaUser")->findAll();

        if (0 === count($users)) {
            $view = $this->view("No WeenestaUser found.", 404);
            return $this->handleView();
        }

        $view = $this->view($users)
                     ->setTemplateVar('users')
                     ->setTemplate($template);

        return $this->handleView($view);
    }
}

On créé la template Twig :

#src/ExampleBundle/Resources/views/WeenestaUser.html.twig
{% if errors is defined %}
  {{ errors }}  
{% else %}
  {% if users is defined %}
    {{ users | serialize }}
  {% else %}
    {{ user | serialize }}
  {% endif %}
{% endif %}

Et voila, vous avez créé votre première API avec le framework symfony !

Vous pouvez retrouver l'intégralité du code source sur GitHub.

Vous pouvez y accéder sur votre serveur web...

A très bientôt,

Mathieu