Pourquoi une contrainte Composer Drupal mal choisie casse une mise à jour
Un composer.json trop strict bloque la montée de version. Un composer.json trop large la rend imprévisible. Chaque contrainte de version doit annoncer précisément ce que vous acceptez de voir changer : la plage de PHP, la majeure de Symfony, et les modules contrib qui suivent, ou pas.
Drupal avance par majeures, de la 10 à la 11, puis vers la 12. À chaque saut, le plancher PHP monte, la version de Symfony change, et certains modules contrib ne suivent pas tout de suite. Si vos contraintes Composer n’ont pas anticipé ce mouvement, la résolution de dépendances échoue au pire moment : au milieu d’une mise à jour, ou pire, en pipeline de déploiement.
Les opérateurs Composer à connaître avant de toucher composer.json
Composer accepte plusieurs façons d’exprimer une contrainte de version, et elles ne se comportent pas du tout pareil.
Le caret (^) : mise à jour non cassante
L’opérateur ^ autorise toute mise à jour qui ne casse rien jusqu’à la prochaine version majeure, et c’est celui que Composer recommande pour écrire du code de bibliothèque, dans un souci d’interopérabilité maximale (documentation Composer). Sur le composer.json racine d’un projet applicatif, la question se pose différemment : vous voulez souvent plus de contrôle sur ce qui entre lors d’une mise à jour.
Le tilde (~) : verrouiller le périmètre
Avec ~1.2, la contrainte équivaut à >=1.2 <2.0.0 ; avec ~1.2.3, elle équivaut à >=1.2.3 <1.3.0 (documentation Composer). Vous choisissez la granularité du verrou en ajoutant ou en retirant un chiffre.
Plages explicites et exclusions (conflict)
Composer accepte aussi des plages écrites avec des opérateurs de comparaison (>, >=, <, <=, !=), combinables en ET ou en OU (documentation Composer). Le core de Drupal s’en sert pour exclure certaines versions problématiques via la clé conflict : la branche 11.x exclut par exemple les versions de Drush antérieures à 12.4.3 (composer.json du core 11.x). Une exclusion dit « jamais cette version », là où une plage dit « seulement entre ces bornes ».
PHP et Composer : des planchers qui montent à chaque majeure (10→11→12)
Chaque majeure de Drupal relève son plancher PHP. Drupal 10 (branche 10.4.x) exige PHP 8.1.0 ou plus (composer.json du core 10.4.x). La branche 11.x exige PHP 8.3.0 ou plus (composer.json du core 11.x). Le guide de montée vers Drupal 12 publié par drupal.org annonce déjà PHP 8.5.0 ou plus (guide de montée vers Drupal 12). Un composer.json parfait ne compense pas un serveur resté sur une version PHP trop ancienne : la version PHP de l’hébergement se vérifie avant de toucher à la moindre contrainte Composer.
Extensions PHP requises ou seulement suggérées
Le core déclare ses extensions PHP via des pseudo-paquets ext-*, comme ext-gd (composer.json du core 11.x). Toutes ne sont pas au même niveau d’obligation : ext-zip n’est pas requise par le core 11.x, seulement suggérée, pour l’archivage au format ZIP (composer.json du core 11.x). Avant une montée de version, la distinction compte : une extension requise conditionne l’installation, une extension suggérée reste optionnelle.
La version de Composer exigée par chaque majeure
L’outil Composer lui-même a son propre plancher par majeure Drupal. Drupal 10 nécessite Composer 2.3.6 ou plus, et Drupal 11 nécessite Composer 2.7.0 ou plus depuis un correctif de sécurité publié en février 2024 (exigences Composer de Drupal). Drupal.org recommande Composer 2.9.3 pour la montée vers Drupal 12 (guide de montée vers Drupal 12). La version de Composer installée sur vos serveurs de production et vos runners CI compte autant que celle de votre poste.
Symfony et les plugins Composer : ce que change chaque majeure
Drupal s’appuie sur des composants Symfony pour une bonne partie de son core. Si une librairie de votre projet contraint explicitement une version de Symfony, elle doit accepter la majeure exigée par la version de Drupal ciblée ; accepter les deux majeures n’est nécessaire que si vous voulez un seul composer.json valable à la fois sur Drupal 10 et Drupal 11.
Le saut Symfony 6.4 → 7.4
Le core Drupal 10 (branche 10.4.x) requiert Symfony en ^6.4, par exemple pour symfony/console (composer.json du core 10.4.x). La branche 11.x requiert ^7.4 (composer.json du core 11.x). Une librairie qui contraint explicitement une version de Symfony peut bloquer la montée vers Drupal 11 si elle ne couvre pas ^7.4.
Autoriser un nouveau plugin Composer (symfony/runtime)
Drupal 11.4 ajoute symfony/runtime comme dépendance. C’est un plugin Composer, et vous devez l’autoriser explicitement avant qu’il puisse s’exécuter pendant une mise à jour (guide de montée vers Drupal 11). Sans cette autorisation dans la clé allow-plugins de votre composer.json, le plugin ne s’exécute pas, et les tâches qu’il porte ne sont pas appliquées. Au passage, Drupal 11 a aussi supprimé les mises à jour de core antérieures à la version 10.3.0 : passez par ce palier avant d’envisager la 11 (guide de montée vers Drupal 11).
Modules contrib : quand pinner, quand élargir
Pour vos modules contrib, le choix de contrainte dépend de ce que vous cherchez à garantir.
La contrainte exacte, pour verrouiller strictement
Composer permet de spécifier une version exacte d’un paquet : il n’installera que cette version, et uniquement elle (documentation Composer). C’est utile pour un module sensible dont vous voulez contrôler chaque changement, mais la résolution échoue dès qu’une autre dépendance exige une version différente de ce même paquet.
Une contrainte multi-version avec ||
Pour un module contrib compatible avec deux majeures de Drupal à la fois, drupal.org recommande d’élargir la contrainte avec un OU logique plutôt que de forker le module. L’exemple donné par le guide 11→12 : faire passer drupal/linkit de ^6.1 à ^6.1 || ^7.0 (guide de montée vers Drupal 12). C’est l’approche à privilégier quand un module publie une version compatible avec la nouvelle majeure sans abandonner l’ancienne : vous gardez un seul composer.json, sans branche parallèle à maintenir.
Le Lenient Composer Plugin, outil de test, jamais de prod
Pour tester un module avec un nouveau core majeur sans respecter ses contraintes déclarées, il existe le Drupal Lenient Composer Plugin. Il ne doit pas être utilisé en production (documentation du plugin Lenient). Il a sa place dans votre environnement de test, pour évaluer la compatibilité réelle d’un module avant qu’il publie une release officielle, jamais pour contourner une incompatibilité dans un site en ligne.
Tester la résolution avant de casser le pipeline CI
Trois commandes Composer et un outil de détection couvrent l’essentiel pour vérifier qu’une mise à jour de contraintes tient avant de la committer.
composer validate avant de committer
Composer recommande de lancer composer validate avant de committer vos fichiers composer.json et composer.lock, et avant de tagger une release (documentation CLI Composer). Placez cette commande en première étape de votre pipeline CI : elle attrape les erreurs de syntaxe et les contraintes mal formées avant qu’elles atteignent la résolution de dépendances.
composer update --dry-run et composer why-not
L’option --dry-run de composer update simule la commande sans rien exécuter réellement (documentation CLI Composer) : elle montre ce qui changerait sans toucher à votre vendor/. Pour identifier précisément ce qui bloque une montée vers une nouvelle majeure, drupal.org documente la commande composer why-not drupal/core ^12, qui pointe le paquet responsable du conflit (guide de montée vers Drupal 12).
composer audit : sécurité des dépendances en pipeline
composer audit vérifie les paquets installés contre des politiques de dépendances, dont les avis de sécurité connus (documentation CLI Composer). Enchâîné après validate et avant why-not, il complète le contrôle de résolution par un contrôle de sécurité, dans la même étape CI.
Upgrade Status et Drupal Rector en amont
Le guide 11→12 recommande d’utiliser Drupal Rector et Upgrade Status pour remplacer le code déprécié depuis Drupal 10 (guide de montée vers Drupal 12). Upgrade Status, plus largement, sert à évaluer la compatibilité globale d’un site avec une nouvelle majeure, tous projets confondus, contrib comme custom (documentation Upgrade Status). Faites tourner ce rapport avant de modifier la moindre contrainte Composer : il vous dit où regarder en premier.
Garder la main sur le rythme
Aucune de ces commandes ne remplace la lecture du changelog d’une majeure. Mais ensemble, elles vous donnent un filet avant chaque mise à jour : composer validate pour la forme, --dry-run et why-not pour la résolution, audit pour la sécurité, Upgrade Status pour le reste du code. La procédure officiellement documentée pour passer à Drupal 12 suit la même logique en deux temps sur le core lui-même : fixer ^12 sur les paquets core avec --no-update, puis résoudre ensuite en une étape séparée (guide de montée vers Drupal 12). Déclarer la contrainte d’abord, résoudre ensuite : la même séquence que celle que nous recommandons sur vos modules contrib.
Si votre composer.json accumule les contraintes figées au fil des années et que chaque montée de version vire au casse-tête, nous pouvons regarder avec vous où se trouve le vrai verrou. Demander un diagnostic.
À lire aussi
- Drupal 12 en bêta : plan d’action concret pour décider, tester et anticiper — cadrer la migration, tester les dépendances et préparer la bascule.
- Drupal 12 en vue : cartographier vos dépendances avant d’acter la bascule — inventaire des modules contrib, custom et des surcharges, avec critères de go/no-go.
- Drupal 7 en 2026 : ce que l’arrivée de Drupal 12 change pour les sites restés en Drupal 7 — viser Drupal 11 ou attendre Drupal 12 ?