Le 24 septembre, l’équipe PHP a publié la première release candidate de PHP 8.6, numérotée RC2 : la RC1, victime d’une erreur d’empaquetage, n’a jamais été annoncée. Elle est sortie en même temps que des versions correctives pour toutes les branches encore supportées, et la GA est annoncée pour le 19 novembre. Une RC est gelée fonctionnellement : plus aucune nouvelle fonctionnalité, seulement la chasse aux régressions, et c’est aux utilisateurs de la faire. Mon avis : personne ne migre un legacy vers une RC, mais tout le monde devrait la faire tourner dès maintenant dans sa CI. Les dépréciations coûtent presque rien à corriger. Ce qui mérite votre attention, ce sont trois valeurs par défaut de session qui changent, parce qu’elles ne produisent aucun avertissement.
Ce qui arrive dans la 8.6
Les nouveautés les plus commentées sont l’application partielle de fonctions (str_replace(' ', '-', ?) renvoie une closure), la fonction clamp(), les valeurs par défaut sur les propriétés readonly et la classe Time\Duration. Elles sont agréables, aucune n’est urgente pour un projet qui vit sur PHP 7.4 ou 8.1.
La partie qui concerne le code existant est dans le fichier UPGRADING de la branche. J’y ai relevé trois familles de changements :
| Famille | Changement | Gravité pour un legacy |
|---|---|---|
| Sessions | session.use_strict_mode passe à 1, session.cookie_httponly à 1, session.cookie_samesite à Lax | Élevée (silencieux) |
| Fonctions dépréciées | is_double(), is_long(), is_integer(), doubleval(), strcoll(), spl_object_hash(), metaphone() | Faible (avertissement) |
| Syntaxe | return dans un bloc finally, identifiants let, is et _ | Faible à moyenne |
D’autres points de détail figurent dans le même fichier : trim() retire désormais aussi le saut de page (\f) par défaut, et array_intersect() convertit les valeurs en chaînes pendant le balayage. Je les mentionne pour mémoire, ils touchent rarement du code réel.
Les dépréciations : un travail de grep
Les remplacements sont mécaniques, et la documentation les nomme un par un : is_float() pour is_double(), is_int() pour is_long() et is_integer(), floatval() pour doubleval(), spl_object_id() pour spl_object_hash(), Collator::compare() pour strcoll().
Avant de toucher quoi que ce soit, mesurez. Un balayage rapide dit si vous parlez de dix lignes ou de mille :
rg -n --type php '\b(is_double|is_long|is_integer|doubleval|strcoll|spl_object_hash|metaphone)\s*\(' src/ lib/ \
| tee /tmp/deprecations-8.6.txt | wc -l
Deux précautions. Le grep ne voit pas les appels dynamiques ($fn = 'is_long'), et il remonte aussi le code des dépendances si vous l’étendez à vendor/. Pour vendor/, ne corrigez rien : notez les paquets concernés et regardez s’ils ont une version compatible. Une dépendance abandonnée qui appelle spl_object_hash() sera un vrai sujet, pas une ligne à remplacer.
Le cas return dans finally mérite un mot, parce qu’il masque parfois un bug plutôt qu’un style :
function loadConfig(string $path): array
{
try {
return parse($path);
} finally {
return []; // avale l'exception et le résultat : dépréciée en 8.6
}
}
Ici, le return du finally écrase le résultat du try et supprime toute exception en vol. Corriger l’avertissement peut donc changer le comportement observable. Avant de le retirer, cherchez ce qui dépend de ce silence.
Les défauts de session : le vrai risque
Trois réglages changent de valeur par défaut, d’après le fichier UPGRADING :
session.use_strict_mode: 1 au lieu de 0. PHP refuse désormais un identifiant de session qu’il n’a pas lui-même généré.session.cookie_httponly: 1 au lieu de 0. Le cookie n’est plus lisible par JavaScript.session.cookie_samesite:Laxau lieu de non défini. Le cookie n’est plus envoyé sur un POST provenant d’un autre site.
Ces défauts sont plus sûrs, et je pense qu’il fallait les changer. Mais un legacy a souvent bâti des habitudes dessus. Les cas que je vérifierais en premier :
- un flux qui fixe l’identifiant de session à partir d’un paramètre d’URL ou d’un en-tête (passerelle SSO maison, application mobile historique) ;
- un script JavaScript qui lit
document.cookiepour retrouverPHPSESSID; - un retour de paiement ou un formulaire externe qui poste vers votre site et compte sur le cookie de session pour retrouver le panier.
Le troisième est le plus traître. Un POST venu d’un domaine tiers n’emporte plus le cookie : l’utilisateur revient sur votre site déconnecté, sans une seule ligne d’erreur dans vos logs. Un mode de paiement qui redirige par POST, ou un fournisseur d’identité en form_post, sont des candidats classiques.
La parade tient en quatre lignes, et elle est valable dès aujourd’hui, sur la version que vous exécutez :
; php.ini (ou pool FPM) : rendre explicite ce qui était implicite
session.use_strict_mode = 1
session.cookie_httponly = 1
session.cookie_samesite = Lax
Fixez ces valeurs sur votre version actuelle, en préproduction d’abord, et observez. Vous découvrez alors les régressions dans un environnement de votre choix, avant que la 8.6 ne vous les impose un jeudi soir. Si un flux exige SameSite=None, décidez-le explicitement pour le cookie concerné, avec Secure, plutôt que de laisser un défaut le décider.
Un job de CI contre la RC
L’objectif n’est pas de déployer la RC, seulement de savoir. Un job non bloquant, qui exécute la suite de tests avec les avertissements affichés, suffit :
# .github/workflows/php-86-rc.yml (extrait)
php-86-rc:
runs-on: ubuntu-latest
continue-on-error: true
steps:
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
with:
php-version: '8.6'
ini-values: error_reporting=-1, display_errors=1
- run: composer install --ignore-platform-req=php+
- run: vendor/bin/phpunit --fail-on-deprecation
Je donne cet extrait comme un point de départ : vérifiez que l’outil que vous utilisez pour installer PHP propose déjà le canal RC. Le drapeau --ignore-platform-req=php+ est là parce que vos dépendances déclarent souvent php: <8.6, ce qui bloquerait l’installation. Il fait aussi apparaître ce qui n’est pas prêt.
Le résultat attendu d’une première exécution est bruyant et sans danger. Comptez les avertissements par paquet, séparez ce qui est dans src/ de ce qui est dans vendor/, et créez un ticket par dépendance bloquante.
Les limites
Une RC n’est pas la version finale : d’après php.net, la RC3 est prévue pour le 8 octobre, et le fichier UPGRADING d’aujourd’hui peut encore bouger d’ici la GA du 19 novembre. Cet article s’appuie sur les notes de version et le fichier de migration ; je n’ai exécuté ni la RC sur une base de code réelle, ni le job de CI ci-dessus.
Ensuite, cette veille ne remplace pas la question du support. D’après php.net, la branche 8.2 n’a plus que le support de sécurité, jusqu’au 31 décembre 2026, et la 8.3 jusqu’au 31 décembre 2027. Les correctifs de sécurité publiés le 24 septembre, selon le changelog de php.net, concernent les versions 8.5.11, 8.4.26, 8.3.35 et 8.2.34 (ces deux dernières en correctifs de sécurité seulement). Si vous êtes encore sur une branche plus ancienne, le sujet immédiat n’est pas la 8.6 : c’est de sortir d’une version qui ne reçoit plus rien.
Enfin, un test vert ne prouve pas l’absence de régression de session. Les flux dont je parle dépendent de services externes et de navigateurs : ils se testent à la main ou avec des tests de bout en bout, pas avec PHPUnit seul.
Concrètement, par où commencer
- Lancez le grep ci-dessus et notez le nombre de lignes. C’est votre premier chiffre, il tient en cinq minutes.
- Inventoriez vos flux de session : SSO, retours de paiement, cookies lus en JavaScript, applications mobiles qui envoient un identifiant.
- Posez les trois réglages de session explicitement sur votre version actuelle, en préproduction, et rejouez vos parcours de connexion et de paiement.
- Ajoutez le job CI non bloquant contre la RC, et regardez le résultat dans une semaine.
- Regardez votre branche PHP : si elle sort du support de sécurité avant la fin de l’année prochaine, le calendrier de migration passe avant la curiosité sur la 8.6.
Sur les montées de version que j’ai menées, le piège n’est presque jamais dans la syntaxe. C’est dans ce que l’ancienne version faisait sans qu’on le lui demande, et que la nouvelle a cessé de faire.
Sources
- PHP: News Archive 2026, php.net, 24 septembre 2026
- No PHP 8.6.0RC1, scherzer.dev, 23 septembre 2026
- UPGRADING de la branche PHP-8.6, php-src, consulté le 29 septembre 2026
- PHP 8.6.0RC2: Release Information, Changelog, and Download links, PHP.Watch, 24 septembre 2026
- What’s new in PHP 8.6, stitcher.io, septembre 2026
- PHP Supported Versions, php.net, consulté le 29 septembre 2026
Sur ce sujet, l’offre de l’atelier : Migration PHP