Je pose mes cartes sur la table : je pense que la décision de True Async de zapper complètement les fonctions colorées est le meilleur choix de design que quiconque ait fait pour la concurrence en PHP, et je préférerais le voir rater PHP 8.6 plutôt que d'atterrir avec ce principe sacrifié. Le projet — actuellement en v0.8.4 et honnêtement étiqueté comme un core expérimental — est suivi sur php.watch avec PHP 8.6 en ligne de mire, et la roadmap vise une v1.0 stable en novembre 2026, pile en même temps que la sortie de 8.6 prévue le 19 novembre. L'Alpha 1 est sortie le 2 juillet, la Beta 1 est attendue vers la mi-août. Le compte à rebours est donc bien réel. Mais la question dont je veux débattre, ce n'est pas de savoir s'il attrapera le train. C'est de savoir si on comprend ce qu'on est en train de signer.

D'abord, pourquoi ce design sans couleur compte autant pour nous en particulier. En JavaScript ou en Python, dès qu'une fonction devient async, tout ce qui l'appelle doit le devenir aussi, et la fracture remonte dans ta base de code comme l'humidité dans un mur. True Async dit : pas de mot-clé, pas d'annotation, pas de réécriture. Tu enveloppes du code ordinaire dans spawn(), et à l'intérieur de cette coroutine, plus de 70 fonctions standard — file_get_contents, fread, curl_exec, PDO avec MySQL et PostgreSQL, socket_read, même sleep() — deviennent discrètement non bloquantes. Hors coroutine, elles se comportent exactement comme elles l'ont toujours fait. Pour un langage avec vingt-cinq ans de bibliothèques synchrones sur Packagist, ce n'est pas une commodité. C'est le seul chemin de migration qui n'exige pas de réécrire l'écosystème.

Et l'ingénierie en dessous est plus sérieuse que le proof-of-concept habituel. Le pooling de connexions pour PDO est intégré, donc deux coroutines ne piétinent pas silencieusement le même handle de base de données. flock(), qui est un syscall véritablement bloquant, est délégué à un pool de threads pour que le reste de tes coroutines continue d'avancer pendant qu'une seule attend un verrou. Il y a spawn_thread() pour du vrai parallélisme CPU, et — celui-là m'a fait me redresser sur ma chaise — un serveur HTTP/1.1, HTTP/2 et HTTP/3 écrit en C, qui tourne dans le processus PHP, sans reverse proxy devant. Les buffers de sortie sont isolés par coroutine. Quelqu'un a réfléchi aux modes de défaillance ennuyeux, et en concurrence, les modes de défaillance ennuyeux, c'est tout le boulot.

Maintenant, le contre-argument honnête, parce qu'il est solide. Les fonctions colorées sont agaçantes, mais agaçantes comme une alarme incendie : le mot-clé async te dit, au point d'appel, que cette ligne peut céder la main, que le monde a pu changer sous tes pieds quand elle rend le contrôle. La transparence de True Async supprime ce signal. Une propriété statique, un singleton mémoïsé, un binding de conteneur Laravel qui suppose qu'une requête égale un univers isolé — tout ça était sûr parce que le modèle shared-nothing de PHP le rendait sûr. Fais tourner le même code en coroutines coopératives dans un seul processus et ces suppositions deviennent des race conditions invisibles dans le diff, parce que le diff, c'est trois appels à spawn() et rien d'autre. Ce qui rend l'adoption facile rend précisément la nouvelle classe de bugs invisible.

Je penche quand même du côté sans couleur, et voilà pourquoi : l'alternative, ce n'est pas un PHP plus sûr, c'est un PHP forké. On a déjà mené cette expérience. AMPHP, ReactPHP et Swoole sont excellents, et chacun a construit un univers parallèle de drivers et de clients parce que la bibliothèque standard ne pouvait pas coopérer. Un core coloré aurait consacré cette segmentation pour toujours — un PDO async et un PDO sync, un Guzzle async et un sync, de la maintenance dupliquée jusqu'en bas. La transparence au niveau du moteur, là où le core Zend, la couche I/O et la couche socket sont modifiés directement, est la seule version de cette histoire où l'écosystème converge au lieu de se scinder. Les bugs de concurrence sont un vrai prix à payer. L'apartheid des bibliothèques en est un plus gros.

Concrètement, ça veut dire que la charge se déplace de la syntaxe vers la discipline, et vers l'outillage. Le mécanisme de Scope — de la concurrence structurée où un groupe de coroutines vit et meurt ensemble, avec une annulation conçue pour ne pas laisser des données écrites à moitié — est ce que je montrerais du doigt à chaque auteur de framework en ce moment, parce que les scopes, c'est comment tu rends les durées de vie de nouveau visibles une fois les mots-clés disparus. Le paquet true-async/ide-helper (une installation Composer en --dev) donne déjà à PhpStorm, PHPStan et Psalm de vrais stubs pour spawn() et await(), et je soupçonne que l'analyse statique finira par faire le travail que le mot-clé async fait ailleurs : signaler l'état mutable partagé qui traverse un point de suspension. Si tu veux tripoter tout ça toi-même, l'extension s'installe sur PHP 8.5+ via leur installeur ou une image Docker — expérimental, pas pour la production, mais tout à fait utilisable.

Alors, est-ce que ça atterrira dans 8.6 ? Personne ne peut le promettre, et je préférerais sincèrement attendre un cycle plutôt que d'hériter d'une API core bâclée qu'on devra supporter pendant une décennie — les trous qui restent, comme les opérations sur les répertoires et les drivers PDO Oracle et SQLite, sont du genre mineur, mais les API du core, c'est pour toujours. Ma question pour toi, c'est celle que je continue de retourner dans ma tête : quand le cycle de vie des requêtes de ton framework se mettra à tourner en coroutines dans un seul processus, quelle est la première supposition de ta propre base de code qui casse ? J'ai une shortlist pour la mienne, et aucune entrée n'est flatteuse. Dis-moi la tienne.