Aller au contenu principal
La newsletter arrive ! Premier envoi très bientôt : laissez votre adresse pour la recevoir.

PHP 8.6 : ce qui est acté, ce qui se joue encore.

PHP 8.6 arrive le 19 novembre 2026 : clamp(), enums débugables, closures optimisées et application partielle de fonctions. Les generics, eux, ont été déclinés.

MAJ 7 min de lecture
Sommaire · 17

PHP 8.6 est entrée dans sa dernière ligne droite : alpha 1 sortie le 2 juillet, feature freeze le 11 août, GA visée le 19 novembre 2026. Écrit en mai à mi-parcours, ce billet a été remis à jour en juillet : la plupart des votes sont tranchés, la colonne « implémenté » s'est allongée. Et un sujet à part : les generics, dont la nouvelle proposition a finalement été déclinée.

Et pour les versions précédentes...

Et pour les versions précédentes...

Et pour les versions précédentes...

Sept RFCs déjà implémentées

Liste vérifiée sur php.watch/versions/8.6/rfcs. Trois méritent qu'on s'y attarde, les quatre autres tiennent en une ligne.

clamp v2

Signature finale (RFC clamp_v2) :

PHP
clamp(mixed $value, mixed $min, mixed $max): mixed

Borne une valeur entre un min et un max. Accepte tout type comparable : entiers, floats, chaînes (tri alphabétique), DateTimeInterface. Remplace max(min($v, $max), $min), motif qu'on retrouve dans la pagination, les dimensions d'image, la normalisation de score. Auteur : kylekatarnls.

Debugable Enums

Le RFC original sur les enums interdisait toutes les méthodes magiques sauf __call, __callStatic, __invoke. Conséquence : impossible d'utiliser __debugInfo() pour customiser la sortie var_dump. Cette restriction saute en 8.6. Désormais une enum peut renvoyer ce qu'elle veut quand on l'inspecte :

enum(Foo::Bar) (1) {
  [0]=> string(14) "Foo::Bar = Baz"
}

(RFC debugable-enums).

enum SortDirection

Une enum native, unbacked (RFC sort_direction_enum) :

PHP
enum SortDirection
{
    case Ascending;
    case Descending;
}

Le choix « unbacked » est explicite : pas de valeur scalaire associée, à chaque application de mapper vers SORT_ASC, 'asc', ou autre selon son besoin.

Les quatre autres

  • isReadable / isWritable reflection methods : checks natifs sur l'accessibilité d'une propriété, utile pour les hydraters et serializers.
  • mysqli_quote_string : quote sans connexion ouverte.
  • Add Form Feed in trim Functions : le caractère \f (form feed, 0x0C) rejoint la liste par défaut des caractères supprimés par trim.
  • Oniguruma maintenance end and end of mbregex : le backend Oniguruma est retiré de ext/mbstring. Les fonctions mb_ereg* continuent à fonctionner avec un backend interne PCRE2.

Cinq RFCs acceptées

Implémentation en cours. Liste complète, focus sur les deux qui changent la façon de coder.

Closure optimizations

Deux gains (RFC closure-optimizations) :

  1. Inférence automatique en static : une closure qui ne peut pas utiliser $this (pas de référence directe, pas de méthode statique appelée, pas de closure imbriquée non-statique, pas de require/include/eval) est convertie en static automatiquement.
  2. Cache des closures stateless : une closure qui ne capture rien et ne déclare aucune variable statique est réutilisée d'un appel à l'autre, la même instance en mémoire. Gain mesuré sur benchmarks synthétiques : « about 80% » selon le RFC.

Effet de bord à retenir : ReflectionFunction::getClosureThis() retourne désormais null pour les closures inférées statiques. Et deux closures stateless lexicalement identiques deviennent le même objet, donc $a === $b peut passer de false à true après upgrade.

Partial Function Application (v2)

Syntaxe finalisée (RFC partial_function_application_v2) :

  • ? : remplace un argument à cette position
  • ... : représente zéro ou plusieurs arguments restants
PHP
$shorten = str_word_count(...);
// $shorten(string $string, int $format = 0, string $characters = "")

$mid = foo(1, ?, 3, ?);
// $mid attend les arguments 2 et 4

Vote : 33 pour, 0 contre, 0 abstention. La v1 de 2021 avait été retoquée sur des cas limites du moteur d'inférence ; cette v2 réduit la surface et passe.

Les trois autres

  • Add pack()/unpack() endianness modifiers for floating-point numbers : les float rejoignent les modifiers < / > qui existaient déjà pour les entiers.
  • Add pack()/unpack() support for endianness modifiers on integers : extension symétrique côté entiers.
  • Exempt input type and value validation from BC Break policy : décision méta, les fixes de validation d'entrée ne déclenchent plus la procédure de BC break complète. Pertinent pour les contributeurs, transparent pour les utilisateurs.

Ce qui était en vote, ce qui reste en discussion

À surveiller pour la fin du semestre, sans garantie de vote favorable.

Depuis le pointage de mai, les urnes ont parlé : #[\Override] for class constants est implémentée, Stream Error Handling Improvements est acceptée. Le sort des cinq autres (PFA optional parameters, ext/uri, secure session defaults, function arguments in errors, SNMP) se suit sur php.watch. Au 18 juillet, « Add ReflectionAttribute::getCurrent() » est en vote actif.

En discussion (toujours, au 18 juillet) : True Async · BackedEnum::values(). La Polling API, elle, a depuis été acceptée.

True Async mérite un mot : c'est la proposition la plus ambitieuse non encore tranchée (RFC true_async). Trois primitives : spawn(), await(), suspend(). Le système englobe les Fibers existants, ajoute un Scheduler et un Reactor (boucle événementielle), un mécanisme de cancellation coopératif, et une détection de deadlock natif. Si ça passe, c'est plus structurant que toutes les autres réunies. Mais le statut Draft suggère qu'on en reparlera surtout pour PHP 9.0.

Le sujet à part : Bound-Erased Generic Types

C'était le retour des generics. Mise à jour de juillet : la proposition a été déclinée, les generics n'entreront pas dans PHP 8.6. L'analyse qui suit reste utile pour comprendre ce qui a été tenté, et pourquoi le débat reviendra. Trois caractéristiques rendaient cette proposition différente des tentatives précédentes.

Scope large

Selon le texte du RFC : « Generic type parameters can be declared on classes, interfaces, traits, functions, methods, closures, and arrow functions. »

Donc tout. Pas un compromis « interfaces seulement » comme certaines propositions intermédiaires.

Type erasure plutôt qu'enforcement runtime

« Type parameters erase to their bound at runtime; the pre-erasure form is preserved for Reflection and consumed by static analyzers. »

Les bornes (<T extends Stringable>) sont vérifiées par les outils d'analyse statique (PHPStan, Psalm). À l'exécution, le moteur traite T comme sa borne, ici Stringable. Aucun coût runtime ajouté. La métadonnée pre-erasure est conservée pour la Reflection, ce qui permet aux IDE et aux libs comme Doctrine de la lire si besoin.

Static analysis plutôt que compile-time enforcement

C'est le compromis explicite : le RFC « emphasizes static analysis rather than compile-time enforcement ». Concrètement, un code générique faux ne sera pas refusé par le parseur PHP, il sera juste détecté comme erreur par PHPStan. La voix de Gmati dans le débat : PHP utilise déjà des generics par docblock (@template) sans enforcement runtime ; cette RFC ne fait que formaliser la pratique dans la syntaxe native.

Ce que ça donnerait

PHP
interface Collection<T>
{
    public function add(T $item): void;
    public function first(): ?T;
}

final class PostCollection implements Collection<Post>
{
    public function add(Post $item): void { /* T = Post */ }
    public function first(): ?Post { /* T = Post */ }
}

À l'exécution, T est traité comme mixed (ou la borne déclarée). Mais PHPStan, Psalm, PHPStorm verront Post et inféreront en conséquence.

Calendrier

Fin de l'histoire pour ce cycle : la RFC a été déclinée, avant même la fin de l'été qu'exigeait le calendrier. Le point de friction sur internals est resté celui du départ : des generics non-enforced créent-ils plus de confusion qu'ils n'en évitent ? Le sujet, ouvert depuis 2016, attendra une prochaine tentative.

La suite

PHP 8.6 ressemble à une release d'incrément propre : des utilities qui rangent du legacy, des optimisations gratuites, et un rendez-vous manqué avec les generics. Prochaines étapes : la beta du 13 août, puis la GA du 19 novembre.

Une coquille, une erreur dans ce billet ? Signale-la-moi.

Ce billet est publié sous licence Creative Commons BY-NC-SA 4.0 (attribution, pas d'usage commercial, partage dans les mêmes conditions).

Vous aimerez aussi

Newsletter

Un mail quand il y a quelque chose à dire

Pas de tracking, pas de pub, pas de "10 astuces pour…". Juste les nouveaux billets et parfois une réflexion en plus.

Activez uniquement ce que vous souhaitez. Vos choix sont conservés 6 mois.

Strictement nécessaires

Indispensables au fonctionnement du site (session, sécurité, préférence d'affichage). Aucune donnée n'est partagée à des tiers et aucun consentement n'est requis.

Toujours actif

Mesure d'audience

Statistiques via Google Analytics (GA4) : pages vues, source du trafic, navigateur et interactions clés. Dépose des cookies de mesure, activés seulement avec votre accord (Consent Mode). Sans publicité ciblée, sans Google Signals, sans partage commercial.

Contenus externes

Affiche les GIF animés hébergés par Giphy (CDN aux États-Unis). À l'affichage d'un GIF, votre adresse IP et votre navigateur sont transmis à Giphy. Sans votre accord, les GIF ne s'affichent pas.