Quand une application Symfony a quelques années, ses fichiers de config/packages/ racontent son histoire : des clés héritées d’une vieille recette, des options ajoutées un jour de panique, d’autres devenues sans effet. Personne ne les relit, parce que rien ne les vérifie avant qu’elles ne cassent. Symfony 8.2, dont le blog officiel déroule depuis mi-septembre la série « New in Symfony 8.2 », ajoute un outil qui s’attaque à ce point aveugle : un JSON Schema de votre configuration réelle, et une commande pour valider vos YAML contre lui. Je pense que c’est l’une des nouveautés les plus utiles pour un projet en fin de chaîne de montées de version, à condition de connaître ses limites, qui sont réelles.
Ce que fait la 8.2
D’après l’article du blog Symfony daté du 23 septembre, quand le conteneur est compilé en mode debug et que symfony/yaml est installé, Symfony génère un fichier config/schema.json. Il fusionne les arbres de configuration de tous les bundles enregistrés, y compris les blocs when@<env>, et il est régénéré à chaque compilation du conteneur, donc synchronisé avec ce qui est installé.
C’est le pendant, pour le YAML, du fichier config/reference.php introduit en 7.4 pour la configuration en PHP. La 7.4 fournissait déjà des schémas pour services.yaml et routes.yaml ; la 8.2 étend la mécanique aux fichiers de config/packages/, ceux qui changent d’un bundle à l’autre.
Côté éditeur, on branche le schéma avec un commentaire en tête de fichier :
# config/packages/framework.yaml
# yaml-language-server: $schema=../schema.json
framework:
secret: '%env(APP_SECRET)%'
ou une fois pour toutes dans VS Code :
{
"yaml.schemas": {
"config/schema.json": "config/packages/**/*.yaml"
}
}
Vous obtenez l’autocomplétion, les descriptions, les valeurs par défaut, et des alertes sur les options inconnues, dépréciées ou du mauvais type. L’article précise que PhpStorm passe par un réglage de mappage de schémas dans ses paramètres.
La partie qui compte pour la CI
L’éditeur aide celui qui écrit. La CI protège tout le monde, et c’est l’autre moitié de la nouveauté. La commande lint:yaml sait maintenant valider contre un schéma, à condition d’installer une bibliothèque :
composer require --dev opis/json-schema
php bin/console lint:yaml config/packages/ --check-schema=config/schema.json
Sans argument, --check-schema lit les commentaires # yaml-language-server: $schema= de chaque fichier. Et pour les emplacements standard, aucun commentaire n’est nécessaire : config/packages/ utilise config/schema.json, routes.yaml et services.yaml utilisent les schémas de leurs composants. Un fichier sans schéma détecté est déclaré valide, ce qui évite les faux positifs bruyants.
Voici comment je l’intégrerais, en tenant compte d’un détail : le schéma n’existe qu’après une compilation du conteneur en debug. C’est mon montage, pas un exemple du blog, à adapter :
# .github/workflows/config-lint.yml (extrait)
config-schema:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
with: { php-version: '8.4' }
- run: composer install --no-interaction
- run: php bin/console cache:warmup --env=dev # compile le conteneur en debug, génère config/schema.json
- run: php bin/console lint:yaml config/packages/ --check-schema=config/schema.json
Le résultat est un garde-fou qui n’existait pas : une option retirée par une mise à jour de bundle, ou une faute de frappe dans une clé, fait échouer la pipeline au lieu de se manifester en production.
Pourquoi c’est précieux sur un legacy
Sur les montées de version Symfony que j’ai menées, le piège n’est presque jamais dans le code applicatif, il est dans la configuration qui a survécu à trois versions. Une clé qui n’a plus d’effet ne lève pas d’erreur, elle est simplement ignorée, et l’équipe croit être protégée par un réglage qui ne fait plus rien. Un schéma qui signale les options inconnues ou dépréciées transforme ce silence en signal.
Le second intérêt est documentaire. Sur un projet repris, config/schema.json donne une vue à jour de tout ce qui est configurable, et l’autocomplétion aide à comprendre ce qui est réellement branché. C’est une petite mesure de rétro-documentation obtenue sans écrire une ligne de doc.
Autre changement de la 8.2 à connaître : un bundle par composant
Le même mois, le blog Symfony a détaillé un changement d’architecture : chaque composant livre désormais son propre bundle (29 nouveaux, dont MessengerBundle, MailerBundle, HttpClientBundle). Pour vos applications, l’article affirme qu’il n’y a rien à changer : les clés framework.* continuent de fonctionner, et l’on peut, si l’on veut, retirer le niveau framework :
# ancien style, toujours valide
framework:
mailer:
dsn: '%env(MAILER_DSN)%'
# nouveau style
mailer:
dsn: '%env(MAILER_DSN)%'
Ce détail touche directement notre sujet, parce que le schéma décrit la configuration telle que les bundles l’exposent. Lisez aussi la liste des ruptures signalées : debug:config framework mailer devient debug:config mailer, l’activation des formulaires n’active plus automatiquement la validation, et quelques classes ont changé d’espace de noms (RedirectController, TemplateController, AsRoutingConditionService, RouteLoaderInterface). Si un script de déploiement ou de diagnostic appelle debug:config framework, il est à revoir.
Les limites
L’article officiel est lui-même clair sur la principale : le schéma décrit l’arbre de configuration statique, et ne peut pas représenter les valeurs qu’un bundle accepte grâce à une normalisation à l’exécution, par exemple une option qui accepte une liste ou une chaîne via une closure beforeNormalization(). Dans ce cas, lint:yaml peut signaler une erreur sur une configuration valide.
Ce que cela veut dire en pratique : ne branchez pas le contrôle en mode bloquant dès le premier jour. Lancez-le d’abord en continue-on-error, triez les faux positifs, et décidez fichier par fichier ce qui est un vrai défaut. Un contrôle bloquant bruyant est vite contourné, et un garde-fou contourné est pire que pas de garde-fou.
Deuxième réserve, factuelle : ces fonctions sont présentées dans la série « New in Symfony 8.2 », donc pour une version que la plupart des projets n’exécutent pas encore. Je n’ai pas testé cette génération de schéma sur une application réelle pour cet article. La valeur pour vous, aujourd’hui, est de préparer la trajectoire, pas de brancher la nouveauté en production demain. Et un schéma valide ne prouve pas qu’une configuration est juste : il vérifie la forme, pas l’intention.
Concrètement, par où commencer
- Regardez ce que votre projet a dans
config/packages/: combien de fichiers, combien datent d’avant la dernière montée de version majeure. - Sur une branche jetable en 8.2 (ou dès que votre calendrier le permet), générez le schéma et ouvrez trois fichiers dans votre éditeur pour voir ce qu’il signale.
- Ajoutez
opis/json-schemaen dépendance de développement et lancezlint:yaml --check-schemaen local, avant d’y penser en CI. - Passez la commande en CI en mode non bloquant, et notez les faux positifs venant de la normalisation.
- Vérifiez vos scripts de déploiement et de diagnostic pour tout appel à
debug:config framework.
La configuration est le code que personne ne teste. Si un schéma vous aide à commencer, c’est déjà un gain sur ce qui reste, sur beaucoup de projets, une zone sans filet.
Sources
- New in Symfony 8.2: JSON Schema for Configuration, Symfony Blog, 23 septembre 2026
- New in Symfony 8.2: One Bundle per Component, Symfony Blog, 18 septembre 2026
- Symfony blog archives for September 2026, Symfony Blog, consulté le 29 septembre 2026
Sur ce sujet, l’offre de l’atelier : Migration Symfony