La réponse courte, pour une équipe qui maintient une application Symfony en production et se demande quoi faire en septembre 2026 : la cible par défaut n’est pas Symfony 8.1, c’est Symfony 7.4. C’est la version de support long terme courante, publiée en novembre 2025, avec des correctifs de bugs jusqu’en novembre 2028 et des correctifs de sécurité jusqu’en novembre 2029. Symfony 8.1, la version stable du moment, voit son support s’arrêter en janvier 2027. Autrement dit, migrer vers 8.1 aujourd’hui, c’est s’engager à remigrer dans quelques mois.
Ce raisonnement paraît évident écrit ainsi, et pourtant beaucoup d’équipes se précipitent sur le numéro de version le plus élevé en pensant prendre de l’avance. Elles prennent surtout un abonnement à la migration permanente.
Où en est réellement Symfony en 2026
L’écosystème Symfony est plus lisible qu’il n’en a l’air, à condition de regarder le calendrier officiel plutôt que la page d’accueil. Au 6 septembre 2026, trois branches sont supportées : 6.4, 7.4 et 8.1. Une quatrième, 8.2, est en développement pour une sortie prévue en novembre 2026.
Le détail qui surprend le plus les équipes qui n’ont pas suivi : Symfony 8.0 est déjà hors maintenance, avec une fin de support fixée à juillet 2026. Une équipe qui aurait migré vers 8.0 début 2026 en pensant faire le grand saut se retrouve donc, quelques mois plus tard, sur une version qui ne reçoit plus rien. Ce n’est pas un accident, c’est le fonctionnement normal du modèle de versions Symfony : les versions non-LTS ont une durée de vie de l’ordre de huit mois.
| Branche | Statut | PHP minimum | Fin des correctifs | Fin de la sécurité |
|---|---|---|---|---|
| 6.4 | LTS, maintenue | PHP 8.1.0 | Novembre 2026 | Novembre 2027 |
| 7.4 | LTS courante | PHP 8.2.0 | Novembre 2028 | Novembre 2029 |
| 8.0 | Non maintenue | PHP 8.4.0 | Juillet 2026 | Juillet 2026 |
| 8.1 | Stable courante | PHP 8.4.0 | Janvier 2027 | Janvier 2027 |
Ce tableau suffit à trancher la plupart des situations. Un projet encore sur Symfony 6.4 a jusqu’en novembre 2026 avant de perdre les correctifs de bugs, et jusqu’en novembre 2027 avant de perdre les correctifs de sécurité. Ce n’est pas une urgence absolue, mais le compte à rebours a commencé, et il ne reste que quelques semaines sur le premier jalon.
LTS ou version stable : le vrai arbitrage
Le choix entre LTS et version stable n’est pas une question de goût technique, c’est une question de capacité opérationnelle. La bonne façon de la poser est celle-ci : à quelle fréquence votre équipe est-elle réellement capable de faire monter le framework de version ?
Si la réponse est « une fois par an, quand on trouve une fenêtre », la LTS est la seule option raisonnable. Symfony 7.4 vous couvre jusqu’en 2029 et vous laisse organiser la prochaine migration sereinement. Si la réponse est « à chaque sortie, on a une chaîne d’intégration qui tourne et une suite de tests fiable », alors suivre les versions stables devient tenable, et même préférable : chaque saut est petit, les dépréciations sont traitées au fil de l’eau plutôt qu’accumulées.
Le piège classique consiste à choisir la version stable pour de mauvaises raisons :
- « On veut les dernières fonctionnalités » : dans la pratique, très peu d'applications métier sont bloquées par l'absence d'une fonctionnalité d'un majeur récent. Le coût de maintenance dépasse presque toujours le gain.
- « Ça fera moins de travail plus tard » : c'est l'inverse. Prendre 8.1 aujourd'hui, c'est planifier une migration vers 8.2 avant janvier 2027, puis vers 8.3, et ainsi de suite.
- « Le client veut la dernière version » : argument légitime commercialement, mais il faut alors budgéter explicitement le cycle de migration récurrent, pas le découvrir après coup.
- « On repart de zéro, autant prendre le plus récent » : le seul cas où c'est effectivement défendable, à condition que l'environnement d'exécution soit déjà sous PHP 8.4.
Une nuance importante pour les prestataires : sur un projet livré puis maintenu par le client, la LTS est presque toujours le bon choix, y compris quand le client demande autre chose. Livrer une application sur une branche dont le support s’arrête dans quatre mois, sans le dire, relève de la dette technique offerte.
PHP 8.4, le prérequis qui bloque la moitié des projets
Avant toute discussion sur Symfony, il faut vérifier une chose : la branche 8.x exige PHP 8.4.0 au minimum, contre PHP 8.2.0 pour la branche 7.x et PHP 8.1.0 pour la 6.4. C’est très souvent là que la migration s’arrête avant d’avoir commencé.
Le calendrier PHP est lui aussi plus serré qu’on ne le croit. PHP 8.3 a quitté le support actif le 31 décembre 2025 et ne reçoit plus que des correctifs de sécurité, jusqu’au 31 décembre 2027. PHP 8.2 sort de son support de sécurité le 31 décembre 2026, dans quelques mois. PHP 8.1 n’apparaît plus du tout dans le tableau des versions supportées de php.net : la branche est en fin de vie complète.
# État réel de l'environnement, pas ce que dit la documentation interne
php -v
composer show --platform | grep '^php'
# Ce que Composer accepterait comme cible
composer why-not symfony/framework-bundle 8.1
La commande composer why-not est celle qui économise le plus de temps en début de projet : elle liste les contraintes qui empêchent effectivement la montée de version, plutôt que de laisser deviner. Sur un projet ancien, la réponse fait souvent une vingtaine de lignes, et le framework n’y est qu’une ligne parmi d’autres.
Si l’application tourne encore sous PHP 8.1 ou 8.2, l’ordre des opérations est clair : monter PHP d’abord, Symfony ensuite. L’inverse ne fonctionne pas, et tenter les deux en même temps rend le diagnostic des régressions beaucoup plus difficile — on ne sait plus si un comportement a changé à cause du langage ou du framework. Le détail de ce que PHP 8.5 apporte concrètement, et de la fenêtre de migration qui reste ouverte, est traité dans notre article sur PHP 8.5 en production.
La méthode de migration en quatre étapes
La documentation officielle Symfony décrit une démarche que l’expérience confirme largement : on ne saute pas un majeur, on s’y prépare depuis le mineur précédent. Concrètement, quatre étapes.
Première étape : atteindre la dernière mineure de la branche courante. Un projet en Symfony 7.1 doit d’abord passer en 7.4. Cette montée-là est censée être non cassante, puisque Symfony garantit la rétrocompatibilité à l’intérieur d’une branche majeure. C’est aussi elle qui fait apparaître les avertissements de dépréciation qui décrivent, littéralement, le travail restant.
Deuxième étape : supprimer toutes les dépréciations. C’est le gros du chantier, et la raison pour laquelle une migration majeure prend du temps. Symfony 8 retire les fonctionnalités dépréciées pendant le cycle 7.x : tout ce qui déclenche un avertissement en 7.4 cassera en 8.x.
Troisième étape : changer la contrainte Composer et corriger ce qui reste. Une fois le projet propre sous 7.4, le passage lui-même est mécanique.
# Sur la branche courante, avant tout changement de majeur
composer update "symfony/*" --with-all-dependencies
# Les dépréciations remontent dans la suite de tests
vendor/bin/phpunit --display-deprecations
Quatrième étape : valider en conditions réelles. Une suite de tests verte ne garantit pas qu’un conteneur de services se compile correctement en production, ni qu’une configuration de cache se comporte pareil sous charge. Un déploiement en préproduction avec un jeu de données représentatif reste indispensable — un point où une chaîne d’intégration continue bien construite fait toute la différence.
L’ordre compte, et l’erreur la plus fréquente est de vouloir en gagner une : changer la contrainte Composer vers le majeur en espérant que les dépréciations se règleront ensuite. Elles ne se règlent pas ensuite, elles se transforment en erreurs fatales toutes en même temps, sans plus aucun message expliquant ce qu’il aurait fallu faire à la place.
Traiter les dépréciations sans y passer un trimestre
Toutes les dépréciations ne se valent pas, et c’est la distinction la plus utile à faire dès le premier inventaire. Une dépréciation directe vient de votre propre code : vous appelez une méthode qui va disparaître, vous pouvez la corriger. Une dépréciation indirecte vient d’un paquet installé dans vendor/ : vous ne pouvez pas la corriger, seulement mettre à jour le paquet ou attendre son mainteneur.
Le tri se fait donc en deux tas, et le second détermine le calendrier réel de la migration bien plus que le premier.
Pour les dépréciations directes, Rector automatise une partie substantielle du travail mécanique, en particulier les remplacements d’API systématiques. Deux précautions, cependant. La première : toujours lancer un --dry-run et relire le diff avant d’accepter quoi que ce soit. Un outil de réécriture automatique appliqué en aveugle sur une codebase mal testée produit des régressions silencieuses qui se découvrent en production. La seconde : Rector ne comprend pas votre logique métier. Il applique des règles syntaxiques. Là où une dépréciation demande un changement d’approche et non de syntaxe, il faut passer à la main.
// Avant : dépendance à une API retirée dans le cycle 7.x
class ProduitController extends AbstractController
{
public function index(): Response
{
$repo = $this->getDoctrine()->getRepository(Produit::class);
return $this->render('produit/index.html.twig', ['produits' => $repo->findAll()]);
}
}
// Après : injection explicite, compatible avec les branches récentes
class ProduitController extends AbstractController
{
public function __construct(private readonly ProduitRepository $produits) {}
public function index(): Response
{
return $this->render('produit/index.html.twig', [
'produits' => $this->produits->findAll(),
]);
}
}
Ce genre de correction paraît anecdotique isolément. Multipliée par soixante contrôleurs, elle représente l’essentiel du budget d’une migration — et c’est précisément ce que Rector traite bien. L’objectif à atteindre avant de changer de majeur est un projet qui ne produit aucun log de dépréciation applicative sous la branche précédente. Tant que ce n’est pas le cas, la migration n’est pas prête, quel que soit l’état de la suite de tests.
Les bundles tiers, principale cause de blocage
Sur les migrations qui dérapent, la cause est rarement le framework lui-même. C’est un bundle tiers qui n’a pas encore publié de version compatible, ou qui n’est plus maintenu du tout.
Le diagnostic est simple à poser mais souvent fait trop tard :
- Inventorier les dépendances directes :
composer show --directdonne la liste réelle, souvent plus courte que ce que l'équipe imagine. - Vérifier la date du dernier commit de chaque bundle critique : un paquet sans activité depuis dix-huit mois ne suivra pas le prochain majeur.
- Identifier les paquets remplaçables par du code maison : beaucoup de bundles installés il y a des années couvrent aujourd'hui une fonctionnalité que le framework fournit nativement.
- Séparer le bloquant du confortable : un bundle d'administration bloquant justifie de décaler la migration, un helper de formatage de dates non.
Cet inventaire a un effet secondaire utile : il révèle souvent des dépendances installées pour un besoin ponctuel, jamais retirées, et qui n’ont plus d’usage réel. Les supprimer réduit mécaniquement la surface de migration et, accessoirement, la surface d’attaque — sujet traité plus en détail dans notre guide sur la sécurité des dépendances avec Composer.
Sur un paquet critique et abandonné, il n’existe que trois issues : le forker et le maintenir, le remplacer, ou renoncer à la migration. Aucune n’est agréable, mais les découvrir en début de projet plutôt qu’au milieu change complètement la conversation avec la direction.
Ce qu'il faut mettre en place pour ne pas revivre ça
Une migration douloureuse est le symptôme d’un projet qui a laissé passer trop de cycles, pas d’un framework hostile. Symfony documente ses dépréciations à l’avance, précisément pour que le travail se fasse au fil de l’eau.
Trois pratiques changent réellement la situation sur la durée. D’abord, faire échouer la chaîne d’intégration sur les dépréciations directes : tant qu’elles ne coûtent rien, elles s’accumulent. Ensuite, mettre à jour les dépendances sur un rythme fixe — un créneau court chaque mois vaut mieux qu’un chantier annuel. Enfin, traiter la montée de version comme une ligne de budget récurrente et non comme un imprévu : une équipe qui a le droit d’y passer du temps le fait ; une équipe qui doit le justifier à chaque fois ne le fait jamais.
C’est aussi une question de discipline quotidienne sur la qualité du code, un sujet que nous avons abordé avec un lead développeur dans notre entretien sur la qualité de code PHP. Un projet dont la suite de tests est fiable migre en quelques jours. Un projet sans tests migre en quelques semaines, avec un risque de régression que personne ne sait mesurer.
Pour les équipes qui partent d’une version antérieure, notre guide de migration de Symfony 6 vers Symfony 7 couvre l’étape précédente, celle qu’il faut avoir franchie avant même de regarder la branche 8.
Sources consultées le 6 septembre 2026 : Symfony Releases (calendrier officiel des versions et du support), Symfony — Upgrading a Major Version (procédure officielle de montée de version majeure), PHP — Supported Versions (calendrier de support des branches PHP).