🔒 Connexion

PHP

Migrer de PHP 5.6 à PHP 8 : ce qui change à chaque version

9 août 2026 · par Romain RICHER

Un jour, votre hébergeur vous annonce que PHP 7.4 ne sera plus proposé. Ou bien un scanner de sécurité affiche une alerte rouge. Ou encore, un plugin refuse de s’installer. Vous voilà devant une migration de version PHP, avec une question simple et une réponse compliquée : qu’est-ce qui va casser ? Cet article passe en revue ce qui change réellement d’une version à l’autre, depuis PHP 5.6 jusqu’aux versions actuelles, en distinguant ce qui se corrige mécaniquement de ce qui demande une relecture.

Les dates de fin de support reflètent la situation en août 2026. Les ruptures de compatibilité décrites, elles, sont définitives : elles ne changeront plus.

Pourquoi migrer, vraiment

La raison la plus souvent avancée est la performance, et elle est réelle : le passage de PHP 5.6 à PHP 7.0 a divisé par deux le temps d’exécution de la plupart des applications, et chaque version depuis a grignoté un peu plus. Mais ce n’est pas l’argument décisif.

L’argument décisif est la sécurité. Chaque branche de PHP reçoit deux ans de corrections de bugs, puis deux ans de correctifs de sécurité seulement, puis plus rien. Une faille découverte après cette date reste ouverte indéfiniment. En août 2026, seules les branches 8.2, 8.3, 8.4 et 8.5 reçoivent encore des correctifs. PHP 8.1 s’est arrêté le 31 décembre 2025, et PHP 8.2 s’arrêtera le 31 décembre 2026 — dans quelques mois.

Autrement dit : si votre site tourne en PHP 7.4, il accumule des années de vulnérabilités non corrigées. Ce n’est pas une question de confort, et le fait que le site « fonctionne encore » ne prouve rien — un serveur non corrigé fonctionne parfaitement jusqu’au jour où quelqu’un s’y intéresse.

Le tableau des versions

Version Sortie Fin de support Ce qu’elle change
5.6 2014 déc. 2018 Dernière de la branche 5
7.0 2015 jan. 2019 Performance doublée, grand ménage
7.4 2019 nov. 2022 Propriétés typées, fonctions fléchées
8.0 2020 nov. 2023 Comparaisons corrigées, JIT, match
8.1 2021 déc. 2025 Énumérations, readonly, fibres
8.2 2022 déc. 2026 Classes readonly, propriétés dynamiques dépréciées
8.3 2023 déc. 2027 Constantes typées, json_validate()
8.4 2024 déc. 2028 Hooks de propriété, visibilité asymétrique
8.5 nov. 2025 déc. 2029 Branche la plus récente

Une règle de lecture utile : PHP sort une version mineure chaque mois de novembre, et retire une branche chaque année. Rester sur une branche revient donc à s’approcher mécaniquement de son échéance.

5.6 vers 7.0 : le grand ménage

C’est la marche la plus haute, et la seule où beaucoup de code cesse purement et simplement de fonctionner. Trois disparitions font l’essentiel du travail.

Les fonctions mysql_* sont supprimées. mysql_connect(), mysql_query(), mysql_fetch_array() : tout l’ancien pilote MySQL a disparu au profit de PDO et de mysqli. Ce n’est pas un renommage. La connexion devient un objet, la gestion des erreurs change, et les requêtes doivent être préparées plutôt que concaténées. C’est du travail — mais c’est aussi l’occasion de corriger d’anciennes injections SQL, car un code écrit avec mysql_query() en contient presque toujours.

Les expressions régulières POSIX sont supprimées. ereg(), eregi(), split() laissent place aux fonctions preg_*. Attention au piège : la syntaxe des motifs diffère. ereg('^[a-z]+$', $s) devient preg_match('/^[a-z]+$/', $s) — il faut ajouter des délimiteurs, et certaines classes de caractères ne se comportent pas pareil.

Le modificateur /e de preg_replace() est supprimé, ce qui est une bonne nouvelle : il exécutait le remplacement comme du code PHP, une porte ouverte spectaculaire. Il faut le reprendre avec preg_replace_callback().

S’ajoute un changement discret mais réel : l’ordre d’affectation de list() s’est inversé, désormais de gauche à droite. Sans conséquence dans la majorité des cas, sauf quand les cibles se recouvrent.

7.0 vers 7.4 : peu de ruptures, beaucoup de confort

La branche 7 est remarquablement stable pour qui la parcourt. Deux suppressions à connaître : l’extension mcrypt disparaît en 7.2 — à reprendre avec openssl ou sodium — et each() y est déprécié, une simple boucle foreach faisant la même chose sans pointeur interne.

Le reste est un gain : types nullables et retour void en 7.1, heredoc enfin indentable en 7.3, et en 7.4 les propriétés typées et les fonctions fléchées (fn($x) => $x * 2), qui allègent beaucoup de code.

7.4 vers 8.0 : la rupture invisible

C’est la version la plus piégeuse, parce que le changement le plus important ne provoque aucune erreur.

Jusqu’à PHP 7, comparer une chaîne et un nombre convertissait la chaîne en nombre. Résultat : 0 == "bonjour" valait true, puisque « bonjour » se convertissait en zéro. Depuis PHP 8, c’est le nombre qui est converti en chaîne, et l’expression vaut false — ce qui est le comportement raisonnable, mais qui inverse la logique de tout code écrit en s’appuyant sur l’ancien.

// PHP 7          PHP 8
0 == "bonjour"    // true          false
"1" == "01"       // true          true
"10" == "1e1"     // true          true
100 == "1e2"      // true          true

Aucun avertissement, aucune ligne dans les journaux : simplement une condition qui bascule. C’est le genre de changement qu’aucun outil ne peut détecter à coup sûr, parce qu’il dépend de ce que contiennent les variables à l’exécution. La seule parade est une suite de tests, ou une relecture attentive des comparaisons avec ==.

Les suppressions franches, elles, sont faciles à repérer : create_function(), each(), les fonctions de magic quotes, money_format(), __autoload(), les constructeurs à la PHP 4 (une méthode portant le nom de sa classe), l’accès aux caractères d’une chaîne par accolades ($s{0} devient $s[0]), et les arguments de implode() dans l’ordre inverse.

Un dernier point mérite attention : l’opérateur @ ne masque plus les erreurs fatales. Du code qui « marchait » en avalant silencieusement ses échecs va soudain s’arrêter — ce qui est une amélioration, mais peut surprendre en production.

En contrepartie, PHP 8.0 apporte les arguments nommés, les types union, l’expression match, la promotion des propriétés dans le constructeur, l’opérateur ?-> et la compilation juste-à-temps.

8.0 vers 8.4 : des dépréciations qui bavardent

À partir de 8.1, les changements prennent la forme d’avertissements de dépréciation plutôt que d’erreurs. Le code continue de fonctionner, mais les journaux se remplissent — et la version suivante finit par trancher.

8.1 déprécie le passage de null à un paramètre non nullable des fonctions internes — strlen(null), htmlspecialchars(null) — ce qui, sur une base de code ancienne, génère des milliers de lignes de journal. Elle apporte les énumérations, readonly, et les fibres.

8.2 déprécie les propriétés dynamiques : affecter $objet->quelqueChose sur une propriété non déclarée. C’est la dépréciation qui touche le plus de code ancien. Elle déprécie aussi l’interpolation "${var}" — à écrire "{$var}" — ainsi que utf8_encode() et utf8_decode(), dont le nom trompeur cachait une conversion depuis l’ISO-8859-1 uniquement.

8.3 est une version calme : constantes de classe typées, json_validate(), attribut #[Override].

8.4 déprécie les types de paramètre implicitement nullables : function f(Foo $x = null) doit s’écrire function f(?Foo $x = null). Mécanique, mais présent partout dans le code écrit avant 7.1. Elle apporte les hooks de propriété et la visibilité asymétrique.

Ce qu’un outil peut faire, et ce qu’il ne peut pas

Une bonne part de ce travail est mécanique. array() en crochets, $s{0} en $s[0], isset($a) ? $a : $b en $a ?? $b, ${var} en {$var}, Foo $x = null en ?Foo $x = null : ces transformations sont des équivalences strictes, elles ne changent ni le résultat ni les cas limites.

C’est ce que fait notre outil de migration de version : vous collez votre code, ou vous déposez une archive de votre projet, vous choisissez la version visée, et il classe chaque point en quatre niveaux — corrigé (réécrit sans risque), à vérifier (réécrit, mais relisez), à reprendre (signalé, votre code n’est pas touché) et information. Tout se passe dans votre navigateur : aucun code n’est envoyé, ce qui compte quand il appartient à un client.

La quatrième catégorie est la plus importante, et c’est celle qu’un outil honnête doit assumer. Un appel mysql_query() ne devient pas du PDO par substitution. Une comparaison == ne se corrige pas sans savoir ce qu’elle compare. Un outil qui produirait ici du code d’apparence correcte rendrait un très mauvais service — le pire résultat n’est pas celui qui échoue, c’est celui qui semble juste.

Une méthode qui tient

Migrer en une seule fois de 5.6 à 8.4 est possible, mais rend le diagnostic difficile quand quelque chose casse. Une progression par paliers coûte un peu plus de temps et en fait gagner beaucoup.

  • Faire l’inventaire d’abord. Passez le code à l’outil avant de toucher au serveur : vous saurez à quoi vous en tenez, et si l’affaire se compte en heures ou en semaines.
  • Monter par étapes. 5.6 → 7.4, puis 7.4 → 8.1, puis 8.1 → 8.4. Chaque palier isole ses propres ruptures.
  • Activer l’affichage des erreurs sur un environnement de test. Les dépréciations sont muettes en production ; ce sont elles qui annoncent la version suivante.
  • Traiter les dépendances séparément. Les bibliothèques tierces se mettent à jour avec Composer, pas à la main — c’est pourquoi l’outil ignore vendor/ par défaut. Réécrire ce code le ferait diverger de sa source, et la prochaine mise à jour effacerait le travail.
  • Ne rien mettre en ligne sans avoir rejoué les parcours critiques. Formulaires, paiement, envois de courriel, exports : c’est là que les comparaisons == se manifestent.

Le cas WordPress

Un site WordPress mérite une précision : le cœur du CMS suit les versions de PHP sans difficulté, et bascule sans rien demander. Ce sont les thèmes et extensions qui posent problème, en particulier un thème sur mesure écrit il y a dix ans, ou une extension dont l’auteur a cessé la maintenance.

La méthode est la même : dupliquer le site sur un environnement de test, changer la version PHP depuis le panneau de l’hébergement, activer l’affichage des erreurs, et parcourir le site. Les extensions abandonnées sont à remplacer, pas à réparer — un code que personne ne maintient reviendra vous chercher à la version suivante.

En résumé

  • La migration est d’abord une affaire de sécurité : en août 2026, tout ce qui est antérieur à PHP 8.2 est sans correctifs.
  • 5.6 → 7.0 est la marche la plus haute : mysql_*, ereg, /e disparaissent franchement.
  • 7.4 → 8.0 est la plus traîtresse : le changement des comparaisons entre chaînes et nombres ne produit aucune erreur, seulement des conditions qui basculent.
  • À partir de 8.1, les changements s’annoncent en dépréciations : lisez les journaux d’un environnement de test.
  • Le mécanique se traite à l’outil, le reste se relit — et la frontière entre les deux doit être dite clairement.

Une migration de version n’est pas un projet passionnant, mais c’est un projet fini : la liste des ruptures est publiée, vérifiable, et se raccourcit à chaque palier franchi. Le plus dur est de commencer, et le meilleur moment reste avant que l’hébergeur ne décide pour vous.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les commentaires sont modérés avant publication.