Skip to Content

Chapitre 3.5 — Démarrer BookLab

Partie 3 : Installation & environnement — Chapitre 5/5 Version de référence : Symfony 7.4 / PostgreSQL 16.

⏱️ TL;DR

  • On crée le projet fil rouge : symfony new booklab --version="7.4.*" --webapp, puis git init.
  • On ajoute Doctrine (composer require orm) et MakerBundle (composer require --dev maker).
  • On connecte une base : PostgreSQL (via Docker) ou SQLite (un fichier, zéro install), puis doctrine:database:create.
  • On génère un premier contrôleur (make:controller HomeController) et une route de santé /api/health qui renvoie du JSON — le premier signe de vie de l’API.
  • symfony serve → l’écran s’affiche. Premier commit. BookLab existe.
  • À partir d’ici, chaque partie ajoute une couche à ce projet.

🎯 Objectifs

  • Initialiser BookLab (projet + git + Doctrine + Maker).
  • Configurer et créer la base de données (PostgreSQL ou SQLite).
  • Créer un premier contrôleur et une route JSON de santé.
  • Servir l’application et réaliser le premier commit.

1. Créer le projet et le dépôt

symfony new booklab --version="7.4.*" --webapp cd booklab git init git add -A && git commit -m "Squelette Symfony 7.4 (webapp) pour BookLab"

ℹ️ symfony new initialise déjà un dépôt git dans la plupart des cas ; si c’est le cas, git init est inutile. Vérifiez avec git status.

2. Ajouter Doctrine et le MakerBundle

composer require orm # Doctrine ORM + DoctrineBundle (via Flex) composer require --dev maker # générateurs make:*

Flex crée config/packages/doctrine.yaml et ajoute DATABASE_URL dans .env. On va maintenant pointer cette URL vers une vraie base.

3. Connecter une base de données

Deux options. Choisissez selon votre confort.

Option A — PostgreSQL via Docker (recommandé, proche prod)

Le compose.yaml fourni déclare déjà PostgreSQL. On le démarre :

docker compose up -d

Avec la Symfony CLI, DATABASE_URL est injectée automatiquement (chapitre 3.2). Si vous n’utilisez pas la CLI, renseignez-la dans .env.local :

# .env.local (non committé) DATABASE_URL="postgresql://app:!ChangeMe!@127.0.0.1:5432/app?serverVersion=16&charset=utf8"

Option B — SQLite (zéro installation, pour démarrer)

Un simple fichier, aucune install de serveur :

# .env.local DATABASE_URL="sqlite:///%kernel.project_dir%/var/booklab.db"

💡 Pour un dev Next.js : SQLite ici, c’est l’équivalent d’un « je démarre avec une base fichier pour ne pas m’embêter ». Parfait pour apprendre ; on passera à PostgreSQL pour tout ce qui touche aux fonctionnalités avancées (types JSON, contraintes, plein texte). BookLab cible PostgreSQL en vrai.

Créer la base

php bin/console doctrine:database:create # Created database "app" for connection named default

(En SQLite, cela crée le fichier var/booklab.db.)

4. Un premier contrôleur : la route de santé

Générons un contrôleur avec le Maker :

php bin/console make:controller HomeController

Puis remplaçons son contenu par une page d’accueil et une route de santé JSON (le premier endpoint que consommera, plus tard, le front Next.js) :

// src/Controller/HomeController.php declare(strict_types=1); namespace App\Controller; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Attribute\Route; final class HomeController extends AbstractController { #[Route('/', name: 'home', methods: ['GET'])] public function index(): Response { return $this->render('home/index.html.twig', [ 'app_name' => 'BookLab', ]); } #[Route('/api/health', name: 'api_health', methods: ['GET'])] public function health(): JsonResponse { return $this->json([ 'status' => 'ok', 'app' => 'BookLab', 'time' => (new \DateTimeImmutable())->format(\DateTimeInterface::ATOM), ]); } }

Deux routes, déclarées par attribut #[Route] (chapitre 1.5) : / rend une page HTML via Twig, /api/health renvoie du JSON via $this->json(...) (un raccourci qui sérialise un tableau en JsonResponse).

Créons le template minimal :

{# templates/home/index.html.twig #} {% extends 'base.html.twig' %} {% block title %}{{ app_name }}{% endblock %} {% block body %} <h1>{{ app_name }}</h1> <p>Le back-office arrive. L'API répond déjà sur <code>/api/health</code>.</p> {% endblock %}

⚠️ Piège MDX/Twig : dans ce cours, les accolades Twig ({{ … }}, {% … %}) sont dans des blocs de code — c’est indispensable, car hors bloc de code, MDX interpréterait { comme du JavaScript. Dans votre projet, ce sont bien sûr des templates Twig normaux.

5. Servir et vérifier

symfony serve -d
  • Ouvrez https://localhost:8000/ → la page « BookLab » s’affiche.
  • Ouvrez https://localhost:8000/api/health → vous obtenez :
{ "status": "ok", "app": "BookLab", "time": "2026-07-09T12:00:00+00:00" }

Vérifiez aussi que le routing est correct en ligne de commande :

php bin/console debug:router # affiche la table des routes : home GET /, api_health GET /api/health, ...

debug:router liste toutes les routes détectées (avec leur nom, méthode, chemin) — un outil que vous consulterez souvent.

6. Premier commit de BookLab

git add -A git commit -m "BookLab : Doctrine + base + route d'accueil et /api/health"

BookLab existe : un projet Symfony 7.4 qui tourne, connecté à une base, avec une première route HTML et une première route JSON. La suite du cours va l’étoffer, partie après partie :

💡 Pour un dev Next.js : à ce stade, mentalement, vous avez fait tourner « l’API backend ». Dans quelques parties, un fetch('https://localhost:8000/api/health') depuis un composant Next.js recevra ce JSON — c’est déjà l’architecture cible en germe.

✏️ Exercices

Exercice 1. Ajoutez une route GET /api/version qui renvoie { "version": "1.0.0" } en JSON. Écrivez la méthode.

✅ Solution

#[Route('/api/version', name: 'api_version', methods: ['GET'])] public function version(): JsonResponse { return $this->json(['version' => '1.0.0']); }

(À placer dans HomeController. Vérifier avec php bin/console debug:router puis un appel à /api/version.)

Exercice 2. Vous n’avez ni Docker ni PostgreSQL et voulez juste avancer. Quelle configuration de base choisissez-vous, et quelle commande crée la base ?

✅ Solution

SQLite : dans .env.local, DATABASE_URL="sqlite:///%kernel.project_dir%/var/booklab.db". Puis php bin/console doctrine:database:create crée le fichier var/booklab.db. Aucun serveur à installer. (On migrera vers PostgreSQL plus tard pour les fonctionnalités avancées.)

Exercice 3. Après avoir ajouté une route, comment vérifiez-vous sans navigateur qu’elle est bien enregistrée ?

✅ Solution

php bin/console debug:router liste toutes les routes (nom, méthode HTTP, chemin). On peut cibler une route précise : php bin/console debug:router api_health. Utile pour confirmer qu’un attribut #[Route] a bien été pris en compte.

🧠 Quiz de révision

1. Quelle commande crée la base de données une fois DATABASE_URL configurée ?

php bin/console doctrine:database:create.

2. Comment renvoie-t-on du JSON depuis un contrôleur ?

Avec $this->json($data) (hérité d’AbstractController), qui sérialise $data en JsonResponse.

3. Quelle commande liste toutes les routes de l’application ?

php bin/console debug:router.

4. Quelle base choisir pour démarrer sans rien installer, et quelle est sa limite ?

SQLite (un fichier). Limite : moins de fonctionnalités avancées que PostgreSQL (types JSON riches, plein texte, certaines contraintes) — on migre ensuite.

5. Où sont déclarées les routes / et /api/health de BookLab ?

Dans src/Controller/HomeController.php, via des attributs #[Route(...)] au-dessus des méthodes index() et health().


Fin de la Partie 3. BookLab tourne : projet Symfony 7.4, base connectée, une route HTML et une route JSON, le tout versionné. L’environnement est prêt ; on peut maintenant plonger dans le cœur du framework.

Prochaine étape : Partie 4 — HTTP, Kernel, Routing, Controllers — comment Symfony transforme une requête en réponse, en détail.