Retour
Bonnes pratiques Symfony pour un projet robuste

Bonnes pratiques Symfony pour un projet robuste

Symfony

24 mai 2026

Symfony est un framework PHP qui permet de développer des applications web de manière rapide, efficace et maintenable. Il offre de nombreux composants réutilisables, des outils de débogage et de test, ainsi qu’une documentation complète et une communauté active.

Mais pour tirer le meilleur parti de Symfony, il faut respecter certaines bonnes pratiques qui garantissent la cohérence, la lisibilité et la sécurité du code. Dans cet article, nous allons passer en revue les principales recommandations officielles de Symfony, ainsi que quelques conseils supplémentaires pour optimiser votre projet.

Créer le projet avec le binaire Symfony

La première étape pour utiliser Symfony est de créer le projet avec le binaire Symfony, un exécutable qui fournit plusieurs utilitaires, dont la création d’applications Symfony basées sur la dernière version stable.

Pour créer un projet Symfony, il suffit d’exécuter la commande suivante :

$ symfony new my_project_directory

Cette commande va créer la structure de répertoires par défaut de Symfony, qui est simple, explicite et indépendante du framework. Voici à quoi elle ressemble :

your_project/
├─ assets/
├─ bin/
 └─ console
├─ config/
 ├─ packages/
 └─ services.yaml
├─ migrations/
├─ public/
 ├─ build/
 └─ index.php
├─ src/
 ├─ Kernel.php
 ├─ Command/
 ├─ Controller/
 ├─ DataFixtures/
 ├─ Entity/
 ├─ EventSubscriber/
 ├─ Form/
 ├─ Repository/
 ├─ Security/
 └─ Twig/
├─ templates/
├─ tests/
├─ translations/
├─ var/
 ├─ cache/
 └─ log/
└─ vendor/

Il est conseillé de respecter cette structure, sauf si votre projet suit une pratique de développement qui impose une organisation différente, comme le Domain-Driven Design (DDD).

Configurer le projet avec des variables d’environnement et des secrets La configuration du projet Symfony se fait principalement dans le répertoire config/, qui contient des fichiers YAML qui définissent les paramètres et les services de l’application.

Parmi ces paramètres, il y a ceux qui concernent l’infrastructure, c’est-à-dire les options qui changent d’une machine à une autre, comme la base de données, le serveur de mail, ou les clés d’API. Ces options ne modifient pas le comportement de l’application, mais seulement son environnement d’exécution.

Pour gérer ces options, il faut utiliser des variables d’environnement, qui sont des valeurs définies dans le système d’exploitation ou dans le serveur web, et qui sont accessibles depuis l’application. Symfony utilise le fichier .env à la racine du projet pour déclarer et initialiser ces variables d’environnement. Par exemple :

# .env
DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db"
MAILER_DSN="smtp://user:pass@localhost"

Ces variables peuvent ensuite être utilisées dans les fichiers de configuration avec la syntaxe %env(VAR_NAME)%. Par exemple :

# config/packages/doctrine.yaml
doctrine:
dbal:
url: '%env(resolve:DATABASE_URL)%'

L’avantage des variables d’environnement est qu’elles permettent de configurer le projet sans modifier le code source, et sans exposer des informations sensibles dans le dépôt Git. En effet, le fichier .env ne doit pas être versionné, mais plutôt ignoré avec le fichier .gitignore. Chaque machine doit avoir son propre fichier .env adapté à son contexte.

Mais alors, comment gérer les informations sensibles, comme les mots de passe ou les clés d’API, qui sont nécessaires au fonctionnement de l’application ? C’est là qu’intervient le système de secrets de Symfony, qui permet de stocker ces informations de manière sécurisée, sans les mettre dans le fichier .env.

Le système de secrets de Symfony repose sur un fichier chiffré, appelé vault, qui contient les valeurs des secrets. Ce fichier est situé dans le répertoire config/secrets/, et il existe un fichier par environnement (dev, prod, etc.). Pour créer le fichier vault, il faut générer une clé de chiffrement avec la commande suivante :

$ symfony console secrets:generate-keys

Cette commande va créer deux fichiers : config/secrets/prod/prod.decrypt.private.php, qui contient la clé privée de déchiffrement, et config/secrets/prod/prod.encrypt.public.php, qui contient la clé publique de chiffrement. La clé privée doit être gardée secrète et ne pas être versionnée, tandis que la clé publique peut être partagée et versionnée.

Pour ajouter un secret dans le fichier vault, il faut utiliser la commande suivante :

$ symfony console secrets:set VAR_NAME

Cette commande va demander la valeur du secret, puis la chiffrer avec la clé publique et l’ajouter dans le fichier vault. Le secret peut ensuite être utilisé dans les fichiers de configuration avec la syntaxe %env(VAR_NAME)%, comme une variable d’environnement classique. Par exemple :

# config/packages/framework.yaml
framework:
secret: '%env(APP_SECRET)%'

L’avantage du système de secrets de Symfony est qu’il permet de protéger les informations sensibles avec un chiffrement robuste, et de les séparer des autres paramètres de configuration. Il facilite aussi le déploiement du projet, en évitant de mettre les secrets dans le fichier .env ou dans des variables d’environnement du serveur.

Organiser le code applicatif avec des services et des autowires Le code applicatif de Symfony se trouve principalement dans le répertoire src/, qui contient les classes PHP qui implémentent la logique métier du projet. Ces classes sont organisées en différents sous-répertoires selon leur rôle :

• Command/ : contient les commandes console, qui sont des scripts exécutables en ligne de commande.

• Controller/ : contient les contrôleurs, qui sont les classes qui gèrent les requêtes HTTP et renvoient des réponses.

• DataFixtures/ : contient les fixtures, qui sont des données de test à charger dans la base de données.

• Entity/ : contient les entités, qui sont les classes qui représentent les objets métier et leurs relations.

• EventSubscriber/ : contient les écouteurs d’événements, qui sont des classes qui réagissent à des événements du cycle de vie de l’application.

• Form/ : contient les formulaires, qui sont des classes qui définissent et traitent les données saisies par les utilisateurs.

• Repository/ : contient les dépôts, qui sont des classes qui gèrent l’accès aux données persistantes.

• Security/ : contient les classes liées à la sécurité, comme les utilisateurs, les fournisseurs d’utilisateurs, les authentificateurs, ou les votants.

• Twig/ : contient les extensions Twig, qui sont des classes qui ajoutent des fonctionnalités au moteur de template Twig.

Ces classes sont des exemples de services, qui sont des objets PHP qui effectuent une tâche spécifique. Un service peut avoir besoin d’un autre service pour fonctionner, par exemple un contrôleur peut avoir besoin du service mailer pour envoyer un email. Ces dépendances sont injectées dans le constructeur du service, ou dans une méthode spécifique.

Pour gérer les services et leurs dépendances, Symfony utilise le conteneur de services, qui est un objet PHP qui crée et stocke les services. Le conteneur de services est configuré dans le fichier config/services.yaml, qui définit les paramètres et les services de l’application.

Par défaut, Symfony utilise l’autowiring, qui est un mécanisme qui permet au conteneur de services de deviner les dépendances des services en se basant sur les types des arguments.

Par exemple, si un contrôleur a besoin du service mailer, il suffit de l’indiquer dans le constructeur :

// src/Controller/ContactController.php
namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Mailer\MailerInterface;

class ContactController extends AbstractController
{
private $mailer;

public function __construct(MailerInterface $mailer)
{
$this->mailer = $mailer;
}

public function sendEmail()
{
// ...
$this->mailer->send($email);
// ...
}
}

Grâce à l’autowiring, le conteneur de services va automatiquement injecter le service mailer dans le constructeur du contrôleur, sans avoir besoin de le configurer manuellement. L’autowiring simplifie la création et l’utilisation des services, en évitant la duplication de code et les erreurs de configuration.

L’autowiring fonctionne pour la plupart des services, mais il peut y avoir des cas où il faut définir explicitement les dépendances ou les options d’un service. Par exemple, si un service a besoin d’un paramètre qui n’est pas un service, comme une chaîne de caractères ou un nombre. Dans ce cas, il faut utiliser le fichier config/services.yaml pour configurer le service. Par exemple :

# config/services.yaml
services:
App\Service\GreetingService:
arguments:
$greeting: 'Hello'

Cette configuration indique au conteneur de services d’injecter la valeur ‘Hello’ dans le paramètre $greeting du service App\Service\GreetingService. Il est possible d’utiliser des variables d’environnement ou des secrets pour configurer les paramètres des services. Par exemple :

# config/services.yaml
services:
App\Service\GreetingService:
arguments:
$greeting: '%env(GREETING)%'

Cette configuration indique au conteneur de services d’utiliser la valeur de la variable d’environnement GREETING pour le paramètre $greeting du service App\Service\GreetingService.

L’organisation du code applicatif avec des services et des autowires permet de structurer le projet Symfony de manière modulaire, claire et efficace. Elle facilite aussi le test et le débogage des services, ainsi que leur réutilisation et leur évolution.

Utiliser les annotations pour définir les routes et les validations Les annotations sont des commentaires spéciaux qui permettent d’ajouter des métadonnées à une classe, une propriété ou une méthode. Symfony utilise les annotations pour définir les routes et les validations des entités, ce qui évite d’avoir à créer des fichiers de configuration séparés.

Les routes sont les chemins d’accès aux contrôleurs, qui déterminent quelle action exécuter en fonction de l’URL et de la méthode HTTP de la requête. Les routes sont définies avec l’annotation @Route au-dessus de la méthode du contrôleur. Par exemple :

// src/Controller/ContactController.php
namespace App\Controller;

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

class ContactController extends AbstractController
{
/**
* @Route("/contact", name="contact", methods={"GET", "POST"})
*/
public function contact()
{
// ...
}
}

Cette annotation indique que la méthode contact() du contrôleur ContactController doit être appelée lorsque l’URL /contact est demandée avec les méthodes HTTP GET ou POST. L’annotation @Route peut prendre plusieurs options, comme le nom de la route, les méthodes HTTP autorisées, les paramètres dynamiques, ou les conditions d’accès.

Les validations sont les règles qui vérifient que les données saisies par les utilisateurs sont conformes aux attentes de l’application. Les validations sont définies avec des annotations au-dessus des propriétés des entités. Par exemple :

// src/Entity/User.php
namespace App\Entity;

use Symfony\Component\Validator\Constraints as Assert;

class User
{
/**
* @Assert\NotBlank
* @Assert\Length(min=3, max=255)
*/
private $username;

/**
* @Assert\NotBlank
* @Assert\Email
*/
private $email;

// ...
}

Ces annotations indiquent que les propriétés $username et $email de l’entité User doivent être non vides, et que $username doit avoir une longueur comprise entre 3 et 255 caractères, et que $email doit être une adresse email valide. Il existe de nombreuses annotations de validation, qui couvrent les cas les plus courants, comme la longueur, le format, la valeur, l’unicité, ou la comparaison.

L’utilisation des annotations pour définir les routes et les validations permet de centraliser la configuration au niveau du code, ce qui rend le projet Symfony plus facile à lire et à maintenir. Il est toutefois possible d’utiliser d’autres formats de configuration, comme le YAML, le XML, ou le PHP, si on préfère séparer la logique du code de la configuration.

Suivre les conventions de codage de Symfony Symfony suit des conventions de codage qui garantissent la qualité, la cohérence et la lisibilité du code. Ces conventions concernent le nommage, le formatage, la documentation, et les bonnes pratiques du code PHP. Il est recommandé de respecter ces conventions pour développer des applications web de qualité avec Symfony.

Voici quelques exemples de conventions de codage de Symfony :

• Les noms des classes doivent être en PascalCase, c’est-à-dire avec une majuscule au début de chaque mot. Par exemple : ContactController, GreetingService, User.

• Les noms des méthodes et des propriétés doivent être en camelCase, c’est-à-dire avec une minuscule au début du premier mot, et une majuscule au début des mots suivants. Par exemple : sendEmail, $mailer, $username.

• Les noms des variables et des paramètres doivent être en snake_case, c’est-à-dire avec des minuscules et des underscores entre les mots. Par exemple : $user_id, $greeting_message.

• Les noms des constantes doivent être en UPPER_CASE, c’est-à-dire avec des majuscules et des underscores entre les mots. Par exemple : APP_SECRET, MAX_LENGTH.

• Les noms des services doivent être en lowercase, c’est-à-dire avec des minuscules et des points entre les mots. Par exemple : mailer, doctrine.orm.entity_manager, security.user_password_hasher.

• Les noms des routes doivent être en lowercase, c’est-à-dire avec des minuscules et des underscores entre les mots. Par exemple : contact, user_profile, blog_post_show.

• Les noms des tables et des colonnes de la base de données doivent être en snake_case, c’est-à-dire avec des minuscules et des underscores entre les mots. Par exemple : user, user_id, blog_post, blog_post_id.

• Le code PHP doit être indenté avec quatre espaces, et non pas des tabulations.

• Les accolades ouvrantes { doivent être placées sur la même ligne que la déclaration de la classe, de la méthode, ou du bloc de code. Les accolades fermantes } doivent être placées sur une nouvelle ligne. Par exemple :

class ContactController extends AbstractController
{
public function contact()
{
// ...
}
}

• Les instructions if, for, foreach, while, switch, try, catch, finally doivent être suivies d’un espace avant la parenthèse ouvrante (. Les parenthèses fermantes ) doivent être suivies d’un espace avant l’accolade ouvrante {. Par exemple :

if ($condition) {
// ...
}

foreach ($array as $key => $value) {
// ...
}

try {
// ...
} catch (Exception $e) {
// ...
} finally {
// ...
}

• Les opérateurs arithmétiques, logiques, d’assignation, de comparaison, et de concaténation doivent être entourés d’espaces. Par exemple :

$a = $b + $c;
$d = $a * $b;
$e = $d / $c;
$f = $e - $a;
$g = $f % $b;
$h = $g ** $c;

if ($a && $b || $c) {
// ...
}

if ($a == $b || $a === $c) {
// ...
}

if ($a != $b || $a !== $c) {
// ...
}

if ($a < $b || $a <= $c) {
// ...
}

if ($a > $b || $a >= $c) {
// ...
}

$message = 'Hello' . ' ' . 'World';

Conclusion

Dans cet article, nous avons vu quelques-unes des bonnes pratiques pour développer des applications web avec Symfony, comme :

• Créer le projet avec le binaire Symfony

• Configurer le projet avec des variables d’environnement et des secrets

• Organiser le code applicatif avec des services et des autowires

• Utiliser des annotations pour définir les routes et les validations

• Suivre les conventions de codage de Symfony

Ces bonnes pratiques ne sont pas obligatoires, mais elles sont fortement recommandées par la communauté et la documentation officielle de Symfony. Elles permettent de créer des applications web qui sont rapides, efficaces et maintenables, et qui respectent les standards et les principes de Symfony.

Nous espérons que cet article vous a été utile et instructif, et qu’il vous aidera à améliorer vos compétences et vos projets avec Symfony. Si vous avez des questions ou des commentaires, n’hésitez pas à les laisser ci-dessous. Merci de votre lecture, et bon codage avec Symfony !