Pourquoi on ne peut pas attendre
Chaque version de PHP n'est maintenue que quelques années. Passé ce délai, plus aucune faille n'est corrigée, et les distributions Linux comme les hébergeurs finissent par la retirer. Toute la branche 7 n'est plus maintenue depuis la fin de PHP 7.4, en novembre 2022. Une application qui en dépend tourne sur un socle que plus personne ne répare.
Ce qui a disparu (et provoque une erreur fatale)
mysql_connect()et toute l'extensionmysql_*: supprimées dès PHP 7.0. Il faut passer à PDO oumysqli, idéalement avec des requêtes préparées — c'est aussi l'occasion de corriger les injections SQL.ereg()et ses variantes : supprimées en PHP 7.0, à remplacer parpreg_match().each()etcreate_function(): supprimées en PHP 8.0, à remplacer parforeachet par des fonctions anonymes.
Ce qui change de comportement sans prévenir
Le piège le plus sournois, car rien ne plante : la comparaison entre un nombre et une chaîne a changé en PHP 8.0.
var_dump(0 == "abc"); // PHP 7 : true PHP 8 : false
var_dump("1" == "01"); // true dans les deux versions
var_dump(0 == ""); // PHP 7 : true PHP 8 : falseUne condition qui laissait passer une valeur vide peut soudain la refuser, ou l'inverse. Il faut rechercher les comparaisons lâches (==) sur des valeurs issues de formulaires ou de la base, et passer en comparaison stricte (===) après avoir vérifié l'intention.
Autre changement : de nombreuses fonctions internes lèvent désormais une TypeError au lieu d'émettre un simple avertissement. Un count() appelé sur null ou un strlen() sur un tableau arrêtait le script avec un warning ; il l'arrête maintenant net.
Les dépréciations à traiter avant qu'elles ne cassent
Les versions 8.1 à 8.4 ajoutent des dépréciations qui deviendront des erreurs plus tard. Les plus fréquentes dans le code ancien :
- passer
nullà une fonction interne qui attend une chaîne (8.1) — typiquementtrim($_POST['champ'])quand le champ est absent ; - créer une propriété dynamique sur un objet sans la déclarer (8.2) ;
- l'interpolation
"${variable}"dans les chaînes (8.2) ; utf8_encode()etutf8_decode()(8.2) ;- appeler
fputcsv()sans préciser le paramètre$escape(8.4).
Attention : beaucoup de serveurs masquent les dépréciations dans leur configuration (E_ALL & ~E_DEPRECATED). Pour un audit de migration, il faut forcer error_reporting(E_ALL) dans l'application, sinon on croit le code propre alors qu'il ne l'est pas.
Notre méthode
- Sauvegarde complète des fichiers et de la base, hors du serveur.
- Analyse statique du code avec un outil comme PHPCompatibility (une règle pour PHP_CodeSniffer) : il liste les fonctions supprimées et les syntaxes incompatibles, fichier par fichier.
- Copie de l'application sur la version cible, journal d'erreurs ouvert, toutes les dépréciations affichées.
- Comparaison des sorties : quand d'autres programmes dépendent de l'application — une application mobile qui interroge une API, par exemple —, nous comparons les réponses de l'ancienne et de la nouvelle version, à l'octet près. C'est le seul moyen d'être sûr de ne rien casser chez les clients de l'API.
- Bascule, puis surveillance du journal d'erreurs les jours suivants.
Sur un hébergement mutualisé, vérifiez aussi le mode d'exécution : certains panneaux d'administration créent les sites en mod_php, avec une seule version de PHP pour tout le serveur. PHP-FPM permet de choisir la version site par site, et de migrer un site à la fois.
Publié le 18/02/2025.