Aller au contenu principal

Anatomie d’un projet Symfony.

Découvrez l'anatomie d'un projet Symfony. Comprenez le rôle de chaque dossier (bin, config, public, src, var, vendor) pour organiser votre code efficacement.

MAJ 7 min de lecture
Sommaire · 17

Clonez un projet Symfony que vous n'avez jamais vu, et vous tombez sur une douzaine de dossiers aux noms courts : bin, config, public, src, var. La bonne nouvelle : ils sont toujours là, toujours au même endroit, avec toujours le même rôle. Cette régularité n'est pas de la bureaucratie, c'est une carte. Une fois qu'on l'a en tête, on arrête de chercher où poser son code.

Ce billet fait le tour du propriétaire, dossier par dossier : à quoi sert chacun, lesquels on ne touche jamais, et où regarder quand ça plante. À la fin, vous saurez lire l'arborescence d'un projet inconnu en un coup d'œil, et savoir d'instinct où va une nouvelle classe.

Vue d'ensemble

Voici l'ossature d'un projet Symfony récent, réduite à l'essentiel :

mon-projet/
├── bin/
│   └── console
├── config/
│   ├── packages/
│   ├── routes.yaml
│   └── services.yaml
├── public/
│   └── index.php
├── src/
│   ├── Controller/
│   ├── Entity/
│   ├── Repository/
│   └── Kernel.php
├── templates/
├── tests/
├── var/
│   ├── cache/
│   └── log/
├── vendor/
├── .env
├── composer.json
└── composer.lock

Toute la logique de ce rangement tient en une phrase : chaque dossier a une responsabilité, et une seule. Votre code d'un côté, la configuration de l'autre, le code des autres encore ailleurs. Voici la vue d'ensemble avant la visite pièce par pièce.

Le rôle de chaque dossier en un coup d'œil
Dossier Rôle On modifie ?
bin/ exécutables (la console) rarement
config/ comportement de l'application oui
public/ racine web exposée surtout les assets
src/ votre code métier tout le temps
templates/ les vues Twig oui
tests/ les tests automatisés oui
var/ cache et journaux générés jamais (mais on vide le cache)
vendor/ le code des dépendances jamais

bin/ : la console

Ce dossier contient les exécutables de l'application. Le seul que vous manipulez au quotidien s'appelle console. C'est la porte d'entrée vers Symfony en ligne de commande :

Terminal
php bin/console cache:clear
php bin/console make:controller
php bin/console debug:router

Vider un cache, générer un contrôleur, lister les routes, inspecter le conteneur de services : presque tout passe par lui. Un réflexe utile quand on débute : php bin/console list affiche toutes les commandes disponibles, et debug:* regroupe les commandes qui répondent à la question « qu'est-ce que Symfony a compris de ma config ? ».

config/ : la configuration

C'est ici qu'on règle le comportement de l'application, sans toucher à son code. Trois entrées à connaître :

  • routes.yaml : le plan de circulation, quelle URL mène à quel contrôleur.
  • services.yaml : le câblage interne, l'injection de dépendances.
  • packages/ : la configuration de chaque brique tierce (Doctrine, Security, Twig).

Le format par défaut est le YAML. Sa syntaxe est lisible, mais elle se paie : l'indentation fait partie du sens. Une espace de trop ou de moins, et Symfony refuse de démarrer avec un message parfois obscur.

public/ : la racine web exposée

public/ est le seul dossier que le serveur web expose au monde. Il contient index.php, le contrôleur frontal : ce fichier reçoit chaque requête HTTP, démarre le noyau Symfony et renvoie la réponse. Les assets compilés (CSS, JavaScript, images publiques) y vivent aussi.

Le point à retenir dépasse la simple organisation. Tout ce qui n'est pas dans public/ est injoignable depuis un navigateur. Votre code, votre configuration, vos secrets restent hors de portée par construction. C'est une frontière de sécurité, pas juste un dossier.

Zoom sur les assets

src/ : votre code métier

Voici votre espace de travail, la logique propre à votre projet. Symfony n'impose pas grand-chose ici, mais une organisation par responsabilité s'est imposée dans la communauté.

Controller

Il accueille la requête, comprend l'intention, appelle les bons services et retourne une réponse. On le veut mince : il coordonne, il ne calcule pas. Dès qu'un contrôleur se met à contenir de la logique métier, c'est le signe qu'il faut extraire un service.

Pour aller plus loin

Entity et Repository

Une Entity est la représentation objet d'une donnée. Avec Doctrine, chaque entité correspond en général à une table. Le Repository associé est l'endroit où vivent les requêtes : c'est lui qui sait retrouver les objets, en DQL ou via le QueryBuilder. L'entité porte la donnée, le repository sait la chercher.

Service

Le travailleur spécialisé. Envoi d'e-mail, calcul de facture, transformation de données : dès qu'une logique est réutilisable ou un peu complexe, elle va dans un service. C'est ce qui garde le reste du code découplé et testable.

Sujets connexes

EventListener et EventSubscriber

Les observateurs. Ils réagissent à un événement (« utilisateur connecté », « commande payée ») sans modifier le code qui l'émet. Très pratique, à doser : trop d'écouteurs invisibles rendent le flux d'exécution difficile à suivre.

templates/ : les vues Twig

Ici règne Twig, le moteur de gabarits de Symfony. Au-delà de générer du HTML, il apporte deux choses. La sécurité d'abord, avec l'échappement automatique des variables, qui coupe court à la majorité des failles d'injection dans les vues. La modularité ensuite, avec l'héritage et l'inclusion de gabarits, qui évitent de copier-coller le même en-tête partout.

tests/ : les tests

Ce dossier reflète src/. Il abrite deux familles de tests. Les tests unitaires vérifient une classe isolée, souvent un service. Les tests fonctionnels simulent de vraies requêtes HTTP et vérifient que l'application répond correctement de bout en bout. L'un valide une pièce, l'autre valide le bâtiment en marche.

var/ : cache et journaux

var/ est ce que Symfony génère pour tourner. Deux sous-dossiers comptent :

  • cache/ : Symfony y compile sa configuration pour aller vite. On ne l'édite jamais à la main, mais on le vide sans hésiter avec php bin/console cache:clear quand un comportement devient inexplicable.
  • log/ : les journaux de l'application. C'est le premier endroit où regarder quand quelque chose casse.

vendor/ : les dépendances

vendor/ contient le code des autres : Symfony lui-même, Doctrine, Monolog, et toutes vos dépendances. Il est géré de bout en bout par Composer. On n'y modifie jamais un fichier, car la moindre retouche saute à la prochaine mise à jour. Ce dossier ne se committe pas non plus : il se reconstruit tout seul à partir de composer.json et composer.lock.

Pour tout ce qui touche à vendor/ et Composer

Les fichiers à la racine

Trois fichiers méritent votre attention à la racine du projet :

  • composer.json : le manifeste du projet, la liste de ce dont il a besoin.
  • composer.lock : les versions exactes réellement installées, pour que la production soit identique au poste de développement.
  • .env : les variables d'environnement (base de données, clés d'API), souvent surchargées par un .env.local non versionné pour les secrets.

Ce que ce billet ne dit pas

On est resté sur la carte, pas sur chaque recoin. La mécanique interne des bundles, la référence complète de la configuration, l'ordre de résolution des variables d'environnement, les recettes Symfony Flex : autant de sujets qui méritent leur propre visite. Ici, l'objectif était de savoir se repérer, pas de tout démonter.

Se repérer, c'est déjà maîtriser

Cette régularité a un nom chez Symfony : la convention plutôt que la configuration. Le prix à payer est d'accepter une carte qu'on n'a pas dessinée. Le gain est immense : n'importe quel développeur ouvre n'importe quel projet Symfony et sait, en trente secondes, où vit le code métier, où se règle la configuration, et où regarder quand ça brûle.

La prochaine fois que vous récupérez un projet inconnu, ne commencez pas par le code. Ouvrez son src/ et son config/, et demandez-vous : est-ce que je saurais dire ce que fait cette application avant même de lire une ligne de logique ?

Vous vous repérez ?

Quel dossier est le seul exposé au serveur web ?

Voir la réponse

Bonne réponse : public/

Seul public/ est la racine web. Tout le reste (votre code, la config, les secrets) vit en dehors, hors de portée d'un navigateur.
L'application plante. Où regarder en premier ?

Voir la réponse

Bonne réponse : var/log/

var/log/ contient les journaux de l'application. var/cache/ ne stocke que la config compilée, et on ne fouille pas vendor/ pour un bug maison.
Peut-on modifier un fichier dans vendor/ ?

Voir la réponse

Bonne réponse : Non, Composer l'écrase à la prochaine mise à jour

vendor/ est géré par Composer et se reconstruit. Une retouche s'y perd au prochain composer install : on passe par une contribution amont ou un fork.

Une coquille, une erreur dans ce billet ? Signale-la-moi.

Vous aimerez aussi

Activez uniquement ce que vous souhaitez. Vos choix sont conservés 6 mois.

Strictement nécessaires

Indispensables au fonctionnement du site (session, sécurité, préférence d'affichage). Aucune donnée n'est partagée à des tiers et aucun consentement n'est requis.

Toujours actif

Mesure d'audience

Statistiques via Google Analytics (GA4) : pages vues, source du trafic, navigateur et interactions clés. Dépose des cookies de mesure, activés seulement avec votre accord (Consent Mode). Sans publicité ciblée, sans Google Signals, sans partage commercial.

Contenus externes

Affiche les GIF animés hébergés par Giphy (CDN aux États-Unis). À l'affichage d'un GIF, votre adresse IP et votre navigateur sont transmis à Giphy. Sans votre accord, les GIF ne s'affichent pas.