417 mots
2 minutes
Créer une API simple avec Symfony

Avec les frameworks JavaScript, on a de plus en plus besoin d’accéder aux données via une API, et ce sans forcément vouloir sortir l’artillerie lourde (je pense entre autres à l’excellent API Platform).

L’API que nous allons développer sera ultra simple (pas d’authentification, peu de gestion des erreurs, pas de versionning, …).

Elle contiendra 5 routes pour gérer des livres :

  • GET : /api/livre/{id} : Lecture d’un seul livre.
  • GET : /api/livres : Lecture de tous les livres.
  • POST : /api/livre : Création d’un livre.
  • PUT : /api/livre/{id} : Modification d’un livre.
  • DELETE : /api/livre/{id} : Suppression d’un livre.

Création du projet#

Pour démarrer, créez un nouveau projet Symfony avec PHP 8 et Symfony 6 :

symfony new custom-api
symfony server:start

Base de données#

Ajoutez les composants nécessaires pour gérer une base de données et installez le Maker Bundle :

composer require orm
composer require --dev maker-bundle

Configurez votre connexion dans le fichier .env.local :

DATABASE_URL="mysql://login:mdp@localhost:3306/customApi?serverVersion=5.7"

Créez une entité pour représenter un livre :

bin/console make:entity Livre

Mettez à jour la base de données :

bin/console doctrine:database:create
bin/console make:migration
bin/console doctrine:migrations:migrate

Fixtures#

Pour générer des données fictives :

composer require --dev orm-fixtures
composer require fzaninotto/faker --dev
bin/console make:fixtures

Exemple de fixture pour 50 livres :

class LivreFixtures extends Fixture
{
    public function load(ObjectManager $manager): void
    {
        $faker = \Faker\Factory::create('fr_FR');

        for ($i = 0; $i < 50; $i++) {
            $livre = new Livre();
            $livre->setAuteur($faker->firstName . ' ' . $faker->lastName);
            $livre->setTitre($faker->realText($faker->numberBetween(10, 100)));
            $livre->setNbPage(rand(50, 999));
            $manager->persist($livre);
        }

        $manager->flush();
    }
}

Chargez les fixtures :

bin/console doctrine:fixtures:load

Routes GET#

Créez un contrôleur pour gérer les livres :

bin/console make:controller LivreController

Ajoutez une route pour lire un livre spécifique :

#[Route('/api/livre/{id}', name: 'get_livre', methods: ['GET'])]
public function get($id): Response
{
    $livre = $this->entityManager->getRepository(Livre::class)->find($id);
    if (!$livre) {
        return $this->json(null, Response::HTTP_NOT_FOUND);
    }

    return $this->json($livre, Response::HTTP_OK);
}

Ajoutez une autre route pour lire tous les livres :

#[Route('/api/livres', name: 'get_livres', methods: ['GET'])]
public function getAll(): Response
{
    $livres = $this->entityManager->getRepository(Livre::class)->findAll();
    return $this->json($livres, Response::HTTP_OK);
}

Routes POST, PUT et DELETE#

Pour créer un livre :

#[Route('/api/livre', name: 'add_livre', methods: ['POST'])]
public function add(Request $request): Response
{
    $data = json_decode($request->getContent(), true);
    $livre = new Livre();
    $livre->setTitre($data['titre'])->setAuteur($data['auteur'])->setNbPage($data['nbPage']);

    $this->entityManager->persist($livre);
    $this->entityManager->flush();

    return $this->json(['message' => 'Livre créé'], Response::HTTP_CREATED);
}

Pour mettre à jour un livre :

#[Route('/api/livre/{id}', name: 'update_livre', methods: ['PUT'])]
public function update(Request $request, $id): Response
{
    $livre = $this->entityManager->getRepository(Livre::class)->find($id);
    if (!$livre) {
        return $this->json(null, Response::HTTP_NOT_FOUND);
    }

    $data = json_decode($request->getContent(), true);
    $livre->setTitre($data['titre'] ?? $livre->getTitre())
          ->setAuteur($data['auteur'] ?? $livre->getAuteur())
          ->setNbPage($data['nbPage'] ?? $livre->getNbPage());

    $this->entityManager->flush();

    return $this->json($livre, Response::HTTP_OK);
}

Pour supprimer un livre :

#[Route('/api/livre/{id}', name: 'delete_livre', methods: ['DELETE'])]
public function delete($id): Response
{
    $livre = $this->entityManager->getRepository(Livre::class)->find($id);
    if ($livre) {
        $this->entityManager->remove($livre);
        $this->entityManager->flush();
    }

    return $this->json(null, Response::HTTP_NO_CONTENT);
}

Conclusion#

Vous venez de créer une API simple avec Symfony. Le code source complet est disponible sur mon GitHub.