Aller au contenu principal

Migration PHP · 5.6 → 7.0 → 7.1 → 7.2 → 7.3 → 7.4 → 8.0 → 8.1 → 8.2 → 8.3 → 8.4 → 8.5

Migrer de PHP 5.6 à PHP 8.5

PHP 5.6 ne reçoit plus de correctifs de sécurité depuis décembre 2018 ; PHP 8.5 reste couvert par les correctifs de sécurité jusqu’en décembre 2029. La montée traverse 11 versions (7.0, 7.1, 7.2, 7.3, 7.4, 8.0, 8.1, 8.2, 8.3, 8.4 et 8.5), chacune avec ses incompatibilités documentées dans le manuel PHP. 16 ruptures à fort impact sur le parcours. Première rupture à traiter : beaucoup d'erreurs fatales deviennent des exceptions Error ; un set_exception_handler() typé Exception provoque une erreur fatale si une Error est levée.

Où en est le support de PHP 5.6 et 8.5 ?

Support de PHP 5.6 et 8.5
CritèrePHP 5.6PHP 8.5
Sortieaoût 2014novembre 2025
Fin des correctifs de bugsjanvier 2017décembre 2027
Fin des correctifs de sécuritédécembre 2018décembre 2029

Statuts vérifiés le 08/11/2026 sur les pages officielles de version.

Les ruptures à traiter en premier

  1. Bloquant · 7.0Beaucoup d'erreurs fatales deviennent des exceptions Error ; un set_exception_handler() typé Exception provoque une erreur fatale si une Error est levée.source
  2. Bloquant · 7.0Retrait de toutes les fonctions ext/mysql (mysql_*) : il faut migrer vers mysqli ou PDO.source
  3. Bloquant · 7.1Appeler une fonction utilisateur avec trop peu d'arguments lève désormais ArgumentCountError (Error) au lieu d'un simple avertissement.source

Le chemin de migration, étape par étape

Chaque version mineure de PHP a son guide de migration officiel ; on les applique dans l’ordre, avec la CI au vert entre deux étapes. Avant de lancer le chantier, auditer la dette technique avec Bear Scan chiffre la dette qui ralentira chaque étape.

Passer à PHP 7.0

  • BloquantBeaucoup d'erreurs fatales deviennent des exceptions Error ; un set_exception_handler() typé Exception provoque une erreur fatale si une Error est levée.source
  • BloquantRetrait de toutes les fonctions ext/mysql (mysql_*) : il faut migrer vers mysqli ou PDO.source
  • BloquantRetrait des fonctions ereg* (remplacées par PCRE) et de preg_replace() avec le modificateur /e, à remplacer par preg_replace_callback().source
  • À traiterLes erreurs de syntaxe lèvent ParseError : tout eval() doit gérer cette exception.source
  • À traiterL'évaluation des variables indirectes passe en strict gauche-droite : $$foo['bar']['baz'] devient ($$foo)['bar']['baz'], à corriger avec des accolades.source

Extensions

  • Extensions retirées : ereg, mssql, mysql et sybase_ct ; SAPI Apache 1 (apache, apache_hooks) et plusieurs SAPI obsolètes supprimés.source
  • L'extension JSON est remplacée par JSOND : un nombre ne peut plus finir par un point (34.) et une chaîne vide n'est plus du JSON valide.source

Pièges rencontrés en migration

  • foreach par valeur travaille sur une copie du tableau : les modifications faites pendant l'itération ne sont plus vues, ce qui change le comportement de boucles qui ajoutaient des éléments.source
  • list() assigne désormais dans l'ordre de déclaration : list($a[], $a[], $a[]) inverse son résultat par rapport à PHP 5.source

Rector : LevelSetList::UP_TO_PHP_70

Guide officiel de migration vers PHP 7.0

Passer à PHP 7.1

  • BloquantAppeler une fonction utilisateur avec trop peu d'arguments lève désormais ArgumentCountError (Error) au lieu d'un simple avertissement.source

Étape intermédiaire, détaillée sur sa propre page : migration PHP 7.0 → 7.1

Passer à PHP 7.2

  • Bloquantcount() sur une valeur non dénombrable (null, scalaire, objet non Countable) émet un E_WARNING ; très fréquent dans le code hérité de PHP 5.source
  • Bloquanteach() est dépréciée : à remplacer par foreach ou ArrayIterator.source

Étape intermédiaire, détaillée sur sa propre page : migration PHP 7.1 → 7.2

Passer à PHP 7.3

  • À traiterAvec le heredoc flexible, un marqueur de fin apparaissant dans le corps (même indenté) termine la chaîne et peut provoquer une erreur de syntaxe.source
  • À traitercontinue ciblant un switch émet un avertissement : il se comporte comme break, alors que d'autres langages le traitent comme continue 2.source

Étape intermédiaire, détaillée sur sa propre page : migration PHP 7.2 → 7.3

Passer à PHP 7.4

  • À traiterAccéder à null, bool, int, float ou resource comme à un tableau ($null['key']) génère désormais une notice.source
  • À traiterfn devient un mot réservé : il ne peut plus nommer une fonction ou une classe (reste possible pour une méthode ou une constante de classe).source

Étape intermédiaire, détaillée sur sa propre page : migration PHP 7.3 → 7.4

Passer à PHP 8.0

  • BloquantComparaison lâche nombre/chaîne non numérique : on compare désormais en chaîne, donc 0 == 'foo' vaut false. Fait sauter beaucoup de conditions legacy.source
  • BloquantL'opérateur @ ne masque plus les erreurs fatales ; error_reporting par défaut passe à E_ALL et display_startup_errors est activé.source

Étape intermédiaire, détaillée sur sa propre page : migration PHP 7.4 → 8.0

Passer à PHP 8.1

  • BloquantPasser null à un paramètre non nullable d'une fonction interne est déprécié (strlen(null), trim(null)…) : source massive d'avertissements.source
  • BloquantLes méthodes internes non finales exigent un type de retour compatible dans les classes filles ; sinon dépréciation, masquable par #[\ReturnTypeWillChange].source

Étape intermédiaire, détaillée sur sa propre page : migration PHP 8.0 → 8.1

À lire sur le blog : Migration PHP 8.1 vers 8.3 : les incompatibilités que personne ne mentionne

Passer à PHP 8.2

  • BloquantLa création de propriétés dynamiques est dépréciée, sauf avec #[\AllowDynamicProperties] ; stdClass reste autorisée. Impact fort sur les entités et DTO hérités.source

Étape intermédiaire, détaillée sur sa propre page : migration PHP 8.1 → 8.2

À lire sur le blog : PHP 8.6 arrive le 19 novembre, PHP 8.2 expire le 31 décembre

Passer à PHP 8.3

  • À traiterIncrémenter ou décrémenter des chaînes vides ou non numériques est déprécié ; utiliser str_increment(). L'incrément de chaînes non numériques est soft-déprécié.source
  • À traiterrange() durci : TypeError pour objets, tableaux et ressources, ValueError pour un pas à 0 ou négatif sur une plage croissante, avertissement pour une chaîne vide.source

Étape intermédiaire, détaillée sur sa propre page : migration PHP 8.2 → 8.3

À lire sur le blog : Migration PHP 8.1 vers 8.3 : les incompatibilités que personne ne mentionne · Docker multi-stage builds : image PHP 8.3 de 800 Mo à 80 Mo

Passer à PHP 8.4

  • BloquantParamètre implicitement nullable (Type $p = null) déprécié : écrire ?Type ou Type|null. Touche massivement le code hérité et les dépendances.source

Étape intermédiaire, détaillée sur sa propre page : migration PHP 8.3 → 8.4

À lire sur le blog : Doctrine ORM 3.4.0 : Lazy Objects natifs PHP 8.4 en production · Docker PHP 8.4 production : multi-stage, non-root et scan Trivy en CI

Passer à PHP 8.5

  • À traiterLes alias de casts non canoniques (boolean), (integer), (double) et (binary) sont dépréciés ; l'opérateur backtick est déprécié au profit de shell_exec().source
  • À traiterUtiliser null comme index de tableau ou dans array_key_exists() est déprécié ; utiliser une chaîne vide.source
  • À traiter__sleep() et __wakeup() sont soft-dépréciées au profit de __serialize()/__unserialize() ; register_argc_argv sur SAPI non CLI est déprécié.source
  • À traiterNouveaux avertissements : cast d'un float hors plage vers int, cast de NAN, et déstructuration d'une valeur non tableau.source
  • MineurLe réglage disable_classes est supprimé ; 'array' et 'callable' ne peuvent plus servir de nom d'alias dans class_alias().source

Extensions

  • OPcache est toujours compilée dans le binaire et chargée ; opcache.enable et opcache.enable_cli restent honorés.source
  • Nouvelle extension uri ; PDO::FETCH_CLASS suit désormais la sémantique de call_user_func_array() pour les arguments du constructeur.source

Pièges rencontrés en migration

  • Un php.ini avec zend_extension=opcache.so ou php_opcache.dll émet maintenant un avertissement : retirer la ligne et conserver opcache.enable.source
  • Le constructeur PDO::FETCH_CLASS suit la sémantique CUFA : les clés de chaîne deviennent des arguments nommés, et le wrapping automatique des arguments par valeur vers un paramètre par référence est supprimé.source

Rector : LevelSetList::UP_TO_PHP_85

Guide officiel de migration vers PHP 8.5

À lire sur le blog : PHP 8.5 en prod : array_first(), backtraces fatales et --ini=diff · PHP 8.5 `clone with` : Value Objects immutables sans boilerplate DDD

Ce que PHP 8.5 vous apporte

  • 8.5 : Opérateur pipe |> pour chaîner des appels de gauche à droite.source
  • 8.5 : Extension URI toujours active, conforme à RFC 3986 et WHATWG URL.source
  • 8.5 : Attribut #[\NoDiscard] et cast (void) pour signaler qu'ignorer un retour est intentionnel.source
  • 8.5 : clone devient une fonction : clone($obj, withProperties: [...]) permet de réassigner des propriétés readonly pendant le clonage.source
  • 8.5 : Closures et callables de première classe autorisés dans les expressions constantes ; backtraces pour les erreurs fatales.source

Combien coûte cette migration ?

À partir de 1 500 € HT

Pour une migration Bear Upgrade livrée en Merge Requests, Rector tourne d’abord en dry-run sur les transformations mécaniques, Claude Code traite les cas que Rector ne couvre pas, puis un développeur senior relit chaque Merge Request. Votre équipe veut reprendre la main ensuite ? Pensez à former votre équipe à Claude Code. Exemple concret : la migration Symfony d’un e-commerce bordelais, et après la migration, la maintenance des versions garde le socle à jour.

Sur une base aussi ancienne, l’audit d’abord : Bear Scan mesure tests, dépendances abandonnées et code mort avant de fixer le prix de la migration.

Questions fréquentes

Pour aller plus loin

Sources

Votre migration PHP 5.6 → 8.5, livrée en Merge Requests

CI au vert garantie 7 jours après le merge. Un appel de cadrage suffit pour fixer le périmètre, le prix et le délai.