Aller au contenu principal
Retour au blog

Symfony 8.2 : JSON Schema pour la configuration YAML

Symfony 8.2 génère config/schema.json : autocomplétion et validation de tes YAML dans l’IDE, et un contrôle en CI via lint:yaml --check-schema. Limites incluses.

Flavien Métivier · 9 min de lecture
Sommaire · 7 parties

Symfony 8.2 génère automatiquement config/schema.json, un JSON Schema qui décrit toute la configuration de ton application, pour que ton éditeur autocomplète et valide les fichiers YAML de config/packages/. Le même schéma sert en CI via lint:yaml --check-schema. Annoncée le 23 septembre 2026 sur le blog officiel, contribution de Jérôme Tamarelle (PR #62125 pour la génération, #65394 pour le lint), la fonctionnalité arrive dans Symfony 8.2, attendu en novembre 2026.

Ouvre config/packages/framework.yaml et tape une clé de mémoire. Ton éditeur ne dit rien. Il ne connaît ni framework.http_cache, ni messenger.transports, ni les options de security. Tu ouvres la doc, tu lances config:dump-reference, ou tu copies un bloc d'un autre projet. Et si tu te trompes de clé, tu l'apprends à la compilation du conteneur, au mieux.

Pourquoi config/packages/ n’avait pas d’autocomplétion avant Symfony 8.2

Symfony 7.4 avait déjà livré des JSON Schemas pour services.yaml et routes.yaml. Il manquait le dossier où tu passes le plus de temps : config/packages/. La raison est structurelle : chaque bundle définit son propre arbre de configuration, donc le schéma dépend des bundles installés dans ton application. Impossible de publier un schéma figé une fois pour toutes. Symfony 8.2 contourne le problème en le générant à partir de ce que ton application a réellement installé.

Comment Symfony 8.2 génère config/schema.json

Le fichier est écrit quand le conteneur est compilé en mode debug et que symfony/yaml est installé. Il fusionne les arbres de configuration de tous les bundles enregistrés, blocs when@<env> compris, et se régénère à chaque compilation : installe un bundle, et ses options apparaissent dans le schéma. C'est le pendant YAML de config/reference.php, introduit en 7.4 pour la configuration PHP.

Selon la PR #62125, une classe JsonSchemaGenerator du composant Config produit le schéma, et une compiler pass de FrameworkBundle écrit le fichier combiné. Les objets sont imbriqués plutôt qu'aplatis, ce qui garde le schéma lisible. Le découpage de FrameworkBundle en bundles par composant, détaillé dans le premier article de cette série, se reflète directement ici : chaque bundle apporte sa propre branche du schéma.

Activer l’autocomplétion dans VS Code, PhpStorm et Neovim

Ton IDE ne détecte pas le fichier tout seul, le billet le précise. Pour tout éditeur basé sur yaml-language-server (VS Code avec l'extension YAML, Neovim, Emacs), un commentaire en tête de fichier suffit :

yaml
# config/packages/framework.yaml
# yaml-language-server: $schema=../schema.json
framework:
    secret: '%env(APP_SECRET)%'
    # ...

Le chemin est relatif au fichier édité : dans config/packages/<env>/, il devient ../../schema.json. Plutôt que de semer ce commentaire partout, VS Code accepte un mapping unique dans .vscode/settings.json, à versionner pour toute l'équipe :

json
{
    "yaml.schemas": {
        "config/schema.json": "config/packages/**/*.yaml"
    }
}

Sous PhpStorm, le même mapping se règle dans Settings, Languages & Frameworks, Schemas and DTDs, JSON Schema Mappings. Une fois le lien établi, l'éditeur propose les options avec leur description et leur valeur par défaut, et signale les options inconnues ou dépréciées et les valeurs du mauvais type. Remarque de ma part sur le glob : **/*.yaml ne couvre pas l'extension .yml, adapte-le si ton dépôt mélange les deux.

Valider tes fichiers YAML en CI avec lint:yaml --check-schema

L'éditeur protège celui qui écrit ; la CI protège tout le monde, y compris le correctif rapide de 18 h. Depuis Symfony 8.2, lint:yaml vérifie aussi les fichiers contre un JSON Schema, en plus de leur syntaxe. La validation demande une bibliothèque optionnelle :

bash
$ composer require opis/json-schema

L’option --check-schema s’utilise ensuite de deux façons :

Votre dette technique s'accumule ?

Audit complet en 10 jours. Recommandations priorisées et actionnables.

Calculer mon audit →
bash
# validate the given files against a specific schema
$ php bin/console lint:yaml config/packages/ --check-schema=config/schema.json

# validate each file against its own schema
$ php bin/console lint:yaml config/ --check-schema

La seconde forme est la plus pratique : sans valeur, la commande lit le commentaire # yaml-language-server: $schema= que tes éditeurs utilisent déjà. Dans une application Symfony, les emplacements habituels n'en ont même pas besoin :

  • les fichiers de config/packages/ utilisent le config/schema.json généré ;
  • les routes, services, serializer et validator utilisent les schémas de leurs composants ;
  • les fichiers sans schéma sont déclarés valides, donc tu peux lancer la commande sur tout config/.

La PR #65394 apporte des précisions utiles pour une CI. Seuls les schémas locaux sont acceptés : le lint ne touche jamais le réseau. Toutes les violations sont rapportées en un seul passage, chacune avec sa ligne YAML. Et l'auteur explique le choix d'opis/json-schema : l'alternative évaluée laissait passer du contenu invalide en ignorant certains mots-clés voisins de $ref. Pour l'intégrer à ton pipeline, notre article sur une pipeline CI/CD Symfony avec GitHub Actions montre où placer ce genre de garde-fou.

Limites : les faux positifs liés à beforeNormalization()

Le schéma décrit l'arbre de configuration statique. Or certains bundles acceptent des valeurs que seule la normalisation à l'exécution sait interpréter. L'exemple du billet : une option qui n'accepte une liste que grâce à une closure beforeNormalization(). Le schéma ne peut pas représenter ce cas, et lint:yaml peut alors signaler une erreur sur une configuration pourtant valide. La PR #65394 liste les cas connus :

  • les channels d’un handler Monolog écrits sous forme de liste (["!event"]) ;
  • un mapping YAML vide {}, lu comme un tableau vide, qui échoue contre un type objet (exemple : framework.validation.auto_mapping) ;
  • des clés fusionnées par normalisation au niveau parent, comme url dans doctrine.dbal ;
  • une clé requise fournie par le bundle plutôt que par l’application, comme framework.router.resource.

Conséquence pratique : sur une base de code existante, attends-toi à des faux positifs. Traite la première exécution comme un audit, pas comme une vérité. Lance le contrôle en mode informatif, lis la sortie, isole les bundles concernés, et ne le rends bloquant qu'une fois la sortie propre. C'est la même stratégie progressive que pour monter PHPStan en CI jusqu'à zéro warning : un lint trop bruyant finit toujours ignoré.

Faut-il versionner config/schema.json ?

Le billet ne tranche pas. Ce qui suit est mon raisonnement. Versionner le fichier donne l'autocomplétion immédiate à toute l'équipe et un lint CI sans étape de génération, au prix d'un diff à chaque ajout de bundle. Ne pas le versionner garde le dépôt propre, mais impose de compiler le conteneur en debug avant l'éditeur et avant le lint, car --check-schema sans valeur suppose que le fichier existe. Un compromis raisonnable : versionner le fichier, puis vérifier en CI qu'il est à jour après régénération, avec un git diff --exit-code.

Côté migration, rien à craindre : les deux PR sont de pures nouveautés, sans dépréciation ni changement de comportement pour l'existant, et opis/json-schema reste optionnel tant que tu n'utilises pas --check-schema.

Ma lecture

Ce changement ne modifie ni ton architecture ni ton code applicatif. Il supprime une friction que tout le monde supportait : écrire de la config à l'aveugle. L'autocomplétion est un gain net, à activer le jour de la montée en 8.2 : elle ne coûte qu'un .vscode/settings.json partagé. Le contrôle en CI vaut le coup, mais seulement une fois tes faux positifs mesurés. Le vrai gain n'est pas la complétion : c'est qu'une faute de frappe dans config/packages/ se détecte avant le déploiement, avec le numéro de ligne.

  • Vérifie, une fois en 8.2, que config/schema.json apparaît après une compilation en debug.
  • Pose le mapping éditeur pour toute l’équipe.
  • Ajoute opis/json-schema en dépendance de dev et lance lint:yaml config/ --check-schema en local.
  • Catalogue tes faux positifs (Monolog, Doctrine DBAL) avant d’en faire une étape bloquante.
  • Décide si le schéma est versionné ou généré en CI.

Un schéma qui valide la configuration ne remplace pas un regard extérieur sur le reste. Si tu te demandes ce que ton code cache d'autre que des clés YAML mal orthographiées, un Bear Scan donne en dix jours un état des lieux et des recommandations classées par priorité, que ton équipe peut appliquer elle-même.

Cet article vous a été utile ? Partagez-le.

Portrait de Flavien Métivier, fondateur de The Bearded Bear : barbe longue, lunettes, sur fond sombre

Écrit par

Flavien Métivier

Expert PHP/Symfony indépendant depuis 2014, ancien CTO de Kartable et d'Extrabat. Plus de 80 projets menés, de l'audit à la migration.

Mon parcours

À lire ensuite

Votre dette technique s'accumule ?

Audit complet en 10 jours. Recommandations priorisées et actionnables.

Newsletter Bear Bytes

Veille Claude Code, Symfony et PHP, retours d'expérience terrain et conseils techniques, directement dans votre boîte mail.