Lors du SymfonyLive Paris 2026, une présentation a particulièrement retenu mon attention : « Symfony + FrankenPHP : une DX comme vous n’en avez jamais vu », animée par Kévin Dunglas.
Pour ceux qui ne le connaissent pas, Kévin est le créateur de FrankenPHP, d’API Platform et de Mercure. Il a aussi fondé la coopérative Les-Tilleuls.coop. Quand il parle de PHP et de performance, ça vaut le détour.
Ce qui a fait la différence avec d’autres présentations, c’est que rien n’était théorique. Il a tout fait tourner en live : démarrage d’un projet en 3 secondes, rechargement automatique du navigateur dès qu’il modifie un fichier PHP, et même un agent IA (Claude Code) qui codait dans le projet… piloté depuis son téléphone. Le genre de démo qui donne envie de tout migrer en rentrant au bureau.
Cet article est mon retour détaillé sur cette présentation, avec des explications accessibles et des bouts de code pour pouvoir comprendre et tester.
C’est quoi FrankenPHP ?
La stack classique et ses limites
Sur la plupart des projets PHP aujourd’hui, on retrouve cette architecture :
Navigateur → Nginx (ou Apache) → PHP-FPM → Ton application Symfony
Ça implique de configurer deux logiciels séparés : un serveur web (Nginx/Apache) et un gestionnaire de processus PHP (PHP-FPM). Il faut que les deux communiquent correctement, gérer les certificats HTTPS manuellement (avec Let’s Encrypt par exemple), et tout ça représente pas mal de configuration.
Ce que FrankenPHP change
FrankenPHP remplace toute cette chaîne par un seul programme. C’est un serveur web qui embarque PHP directement dedans.
Il est construit par-dessus Caddy, un serveur web moderne écrit en Go (le langage de Google, réputé pour sa rapidité). FrankenPHP intègre le moteur PHP directement dans Caddy, ce qui donne un unique exécutable qui gère tout :
Navigateur → FrankenPHP (Caddy + PHP intégré) → Ton application Symfony
Les fonctionnalités incluses
| Fonctionnalité | Explication |
| HTTPS automatique | FrankenPHP gère les certificats SSL tout seul. Pas besoin de configurer Let’s Encrypt. |
| HTTP/2 et HTTP/3 | Les protocoles web modernes, activés par défaut. Pages plus rapides sans rien faire. |
| Mode Worker | L’application reste en mémoire entre les requêtes (détail juste après). |
| Hot Reload | Le navigateur se met à jour tout seul quand on modifie un fichier. Comme dans l’écosystème JS. |
| Early Hints (103) | Le navigateur commence à charger CSS/JS avant d’avoir reçu la page complète. Jusqu’à 30% de gain à l’affichage. FrankenPHP est le seul serveur PHP à proposer ça. |
| Hub Mercure intégré | Un système pour envoyer des données en temps réel au navigateur (notifications, mises à jour live…), sans installer de logiciel supplémentaire. |
| Binaire autonome | On peut compiler l’application PHP en un seul fichier exécutable, sans aucune dépendance. |
Installation
C’est rapide. Une seule commande :
# Sur Linux ou macOS
curl https://frankenphp.dev/install.sh | sh
# Sur Windows (PowerShell)
irm https://frankenphp.dev/install.ps1 | iex
Pour lancer un serveur sur un projet Symfony :
frankenphp php-server -r public/
# C’est tout ! Va sur https://localhost
Le dépôt GitHub du projet est php/frankenphp, hébergé directement sous l’organisation officielle php. Ça donne une idée du sérieux accordé au projet par la communauté.
Le Mode Worker : pourquoi c’est plus rapide ?
Le fonctionnement classique de PHP
En PHP classique, chaque requête HTTP déclenche la même séquence :
-
- PHP lit tous les fichiers de ton projet
- Il charge le framework Symfony (le conteneur de services, le routeur, la config…)
- Il traite ta requête
- Il renvoie la réponse
- Il jette tout à la poubelle et oublie tout
À la requête suivante ? On recommence de zéro. C’est le modèle « shared-nothing » : rien n’est partagé entre les requêtes.
L’avantage : c’est simple, pas de risque de fuite mémoire.
L’inconvénient : les étapes 1 et 2 sont refaites à chaque fois alors que le code n’a pas changé entre-temps. Sur un gros projet Symfony, ce bootstrapping peut prendre du temps.
Le principe du Worker
L’application Symfony démarre une seule fois et reste en mémoire. Les requêtes suivantes sont traitées directement, sans relire les fichiers ni recharger le framework.
Avec Symfony 7.4+ : rien à changer dans ton code
Depuis Symfony 7.4, le Mode Worker est supporté nativement. Pas de modification dans public/index.php, pas de package à installer (avant la 7.4, il fallait runtime/frankenphp-symfony). Le composant Runtime de Symfony détecte tout seul que FrankenPHP est en Mode Worker et s’adapte.
Il suffit de configurer le Caddyfile (le fichier de configuration de Caddy/FrankenPHP). L’option watch relance automatiquement le worker quand un fichier PHP change. C’est indispensable, sinon les modifications ne sont jamais prises en compte puisque l’application vit en mémoire.
[pastacode lang= »markup » manual= »localhost%20%7B%0A%20%20%20%20root%20public%2F%0A%0A%20%20%20%20php_server%20%7B%0A%20%20%20%20%20%20%20%20worker%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20file%20public%2Findex.php%0A%20%20%20%20%20%20%20%20%20%20%20%20watch%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%7D » message= » » highlight= » » provider= »manual »/]
Pour une application PHP sans framework ?
Pour ceux qui n’utilisent pas Symfony (ou un framework qui gère le worker mode), il faut écrire le script worker soi-même. Le principe :
$myApp->boot()est appelé une seule fois, avant la bouclefrankenphp_handle_request()attend une requête, puis appelle ton$handler- Les superglobales (
$_GET,$_POST,$_SERVER…) sont réinitialisées automatiquement à chaque requête $myApp->terminate()s’exécute après l’envoi de la réponse (l’utilisateur n’attend pas)
[pastacode lang= »markup » manual= »%3C%3Fphp%0A%2F%2F%20public%2Findex.php%0A%0A%2F%2F%20Boot%20your%20app%0Arequire%20__DIR__.’%2Fvendor%2Fautoload.php’%3B%0A%0A%24myApp%20%3D%20new%20%5CApp%5CKernel()%3B%0A%24myApp-%3Eboot()%3B%0A%0A%2F%2F%20Handler%20outside%20the%20loop%20for%20better%20performance%20(doing%20less%20work)%0A%24handler%20%3D%20static%20function%20()%20use%20(%24myApp)%20%7B%0A%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%2F%2F%20Called%20when%20a%20request%20is%20received%2C%0A%20%20%20%20%20%20%20%20%2F%2F%20superglobals%2C%20php%3A%2F%2Finput%20and%20the%20like%20are%20reset%0A%20%20%20%20%20%20%20%20echo%20%24myApp-%3Ehandle(%24_GET%2C%20%24_POST%2C%20%24_COOKIE%2C%20%24_FILES%2C%20%24_SERVER)%3B%0A%20%20%20%20%7D%20catch%20(%5CThrowable%20%24exception)%20%7B%0A%20%20%20%20%20%20%20%20%2F%2F%20%60set_exception_handler%60%20is%20called%20only%20when%20the%20worker%20script%20ends%2C%0A%20%20%20%20%20%20%20%20%2F%2F%20which%20may%20not%20be%20what%20you%20expect%2C%20so%20catch%20and%20handle%20exceptions%20here%0A%20%20%20%20%20%20%20%20(new%20%5CMyCustomExceptionHandler)-%3EhandleException(%24exception)%3B%0A%20%20%20%20%7D%0A%7D%3B%0A%0A%24maxRequests%20%3D%20(int)(%24_SERVER%5B’MAX_REQUESTS’%5D%20%3F%3F%200)%3B%0Afor%20(%24nbRequests%20%3D%200%3B%20!%24maxRequests%20%7C%7C%20%24nbRequests%20%3C%20%24maxRequests%3B%20%2B%2B%24nbRequests)%20%7B%0A%20%20%20%20%24keepRunning%20%3D%20%5Cfrankenphp_handle_request(%24handler)%3B%0A%0A%20%20%20%20%2F%2F%20Do%20something%20after%20sending%20the%20HTTP%20response%0A%20%20%20%20%24myApp-%3Eterminate()%3B%0A%0A%20%20%20%20%2F%2F%20Call%20the%20garbage%20collector%20to%20reduce%20the%20chances%20of%20it%20being%20triggered%0A%20%20%20%20%2F%2F%20in%20the%20middle%20of%20a%20page%20generation%0A%20%20%20%20gc_collect_cycles()%3B%0A%0A%20%20%20%20if%20(!%24keepRunning)%20break%3B%0A%7D » message= » » highlight= » » provider= »manual »/]
Avec Symfony 7.4+, ce code est inutile, tout est géré automatiquement.
Par défaut, FrankenPHP lance 2 fois plus de workers que le nombre de cœurs CPU. En production, il vaut mieux faire des tests de charge pour trouver le bon réglage. La règle de base : nombre de workers × memory_limit doit rester inférieur à la RAM disponible.
Le Hot Reload pour le backend PHP
Ceux qui ont travaillé avec React, Vue ou Vite connaissent le Hot Module Replacement : on modifie un fichier, la page se met à jour dans le navigateur sans rechargement manuel.
Kévin a montré en live que la même expérience existe désormais côté PHP. On modifie un fichier PHP, un template Twig ou un fichier de config YAML, et le navigateur se met à jour dans la foulée.
Le mécanisme en 3 étapes
Étape 1 : Surveillance des fichiers
FrankenPHP scrute en permanence les fichiers du projet. Par défaut, il surveille le pattern ./**/*.{css,env,gif,htm,html,jpg,jpeg,js,mjs,php,png,svg,twig,webp,xml,yaml,yml}.
Étape 2 : Notification via Mercure
Quand un fichier change, FrankenPHP envoie un message au navigateur via Mercure (son système temps réel intégré). Le navigateur écoute via l’API EventSource de JavaScript, qui est native. Pas besoin de WebSocket ni de librairie externe.
Étape 3 : Mise à jour intelligente de la page
Plutôt qu’un rechargement complet (qui ferait perdre l’état des formulaires, la position de scroll…), une librairie JS appelée Idiomorph compare le nouveau HTML avec la page actuelle et ne modifie que ce qui a changé.
Configuration
Voici le Caddyfile complet pour activer le Hot Reload avec le Mode Worker :
[pastacode lang= »markup » manual= »localhost%0A%0A%23%20Active%20le%20hub%20Mercure%20(n%C3%A9cessaire%20pour%20le%20hot%20reload)%0Amercure%20%7B%0A%20%20%20%20anonymous%0A%7D%0A%0Aroot%20public%2F%0A%0Aphp_server%20%7B%0A%20%20%20%20%23%20Active%20le%20hot%20reload%20(rafra%C3%AEchit%20le%20navigateur)%0A%20%20%20%20hot_reload%0A%0A%20%20%20%20%23%20Active%20le%20mode%20worker%20(garde%20l’app%20en%20m%C3%A9moire)%0A%20%20%20%20worker%20%7B%0A%20%20%20%20%20%20%20%20file%20public%2Findex.php%0A%20%20%20%20%20%20%20%20%23%20Red%C3%A9marre%20le%20worker%20quand%20les%20fichiers%20changent%0A%20%20%20%20%20%20%20%20watch%0A%20%20%20%20%7D%0A%7D » message= » » highlight= » » provider= »manual »/]
Côté client
Le serveur détecte les changements, mais il faut aussi que le navigateur écoute ces événements pour mettre à jour la page. FrankenPHP expose l’URL du hub Mercure via la variable $_SERVER['FRANKENPHP_HOT_RELOAD'].
Il faut ajouter le code suivant dans ton layout principal. Voici l’exemple tel quel de la doc officielle FrankenPHP :
[pastacode lang= »markup » manual= »%3C!DOCTYPE%20html%3E%0A%3Ctitle%3EFrankenPHP%20Hot%20Reload%3C%2Ftitle%3E%0A%3C%3Fphp%20if%20(isset(%24_SERVER%5B’FRANKENPHP_HOT_RELOAD’%5D))%3A%20%3F%3E%0A%3Cmeta%20name%3D%22frankenphp-hot-reload%3Aurl%22%20content%3D%22%3C%3F%3D%24_SERVER%5B’FRANKENPHP_HOT_RELOAD’%5D%3F%3E%22%3E%0A%3Cscript%20src%3D%22https%3A%2F%2Fcdn.jsdelivr.net%2Fnpm%2Fidiomorph%22%3E%3C%2Fscript%3E%0A%3Cscript%20src%3D%22https%3A%2F%2Fcdn.jsdelivr.net%2Fnpm%2Ffrankenphp-hot-reload%2F%2Besm%22%20type%3D%22module%22%3E%3C%2Fscript%3E%0A%3C%3Fphp%20endif%20%3F%3E » message= » » highlight= » » provider= »manual »/]
La condition if (isset($_SERVER['FRANKENPHP_HOT_RELOAD'])) fait en sorte que ce code ne s’active que quand FrankenPHP est configuré pour le hot reload. En production, cette variable n’existe pas, donc le code n’est pas inclus.
Pour ceux qui utilisent Symfony, voici l’équivalent :
[pastacode lang= »markup » manual= »%7B%23%20base.html.twig%20%23%7D%0A%7B%25%20if%20app.request.server.has(‘FRANKENPHP_HOT_RELOAD’)%20%25%7D%0A%20%20%20%20%3Cmeta%0A%20%20%20%20%20%20%20%20name%3D%22frankenphp-hot-reload%3Aurl%22%0A%20%20%20%20%20%20%20%20content%3D%22%7B%7B%20app.request.server.get(‘FRANKENPHP_HOT_RELOAD’)%20%7D%7D%22%0A%20%20%20%20%3E%0A%20%20%20%20%3Cscript%20src%3D%22https%3A%2F%2Fcdn.jsdelivr.net%2Fnpm%2Fidiomorph%22%3E%3C%2Fscript%3E%0A%20%20%20%20%3Cscript%0A%20%20%20%20%20%20%20%20src%3D%22https%3A%2F%2Fcdn.jsdelivr.net%2Fnpm%2Ffrankenphp-hot-reload%2F%2Besm%22%0A%20%20%20%20%20%20%20%20type%3D%22module%22%0A%20%20%20%20%3E%3C%2Fscript%3E%0A%7B%25%20endif%20%25%7D » message= » » highlight= » » provider= »manual »/]
À garder en tête : le hot reload ne doit jamais être activé en production. La surveillance de fichiers consomme des ressources et peut exposer des informations internes de l’application.
FrankenPHP tourne enfin sur Windows (sans WSL)
Depuis la sortie de FrankenPHP en 2022, c’était la fonctionnalité la plus demandée par la communauté. Jusqu’en mars 2026, les développeurs sous Windows devaient passer par WSL (Windows Subsystem for Linux), un Linux virtuel dans Windows. Ça fonctionne, mais ça ajoute de la complexité.
Avec la version 1.12.0 (sortie le 6 mars 2026), FrankenPHP tourne nativement sous Windows. Pas de WSL, pas de Docker. Un .exe qui fonctionne directement. Mode Worker, Hot Reload, tout est supporté.
Les benchmarks parlent d’eux-mêmes : sur la même machine Windows Server 2022, FrankenPHP est 3,6 fois plus rapide qu’une configuration Nginx + PHP-FPM. Plus de 260% de gain.
Pourquoi ça a mis autant de temps ?
Kévin a pris le temps d’expliquer le problème technique, et c’est assez instructif.
FrankenPHP est écrit en Go et appelle le moteur PHP (écrit en C) via CGO, le pont entre Go et C.
Le souci :
- Les builds officiels de PHP pour Windows sont compilés avec Visual Studio (l’outil Microsoft)
- CGO ne savait communiquer qu’avec MinGW/GCC (un autre compilateur)
Les deux sont incompatibles. Comme brancher une prise française dans une prise anglaise.
Le déblocage est venu avec Go 1.26 (début 2026) : une contribution de Google a ajouté le support du compilateur Clang de Visual Studio dans CGO. Clang comprend les deux mondes : il accepte les commandes de type GCC (celles que CGO utilise) tout en produisant du code compatible Visual Studio.
Installation sur Windows
[pastacode lang= »bash » manual= »%23%20Installation%20en%20une%20commande%20via%20PowerShell%0Airm%20https%3A%2F%2Ffrankenphp.dev%2Finstall.ps1%20%7C%20iex%0A%0A%23%20Lancer%20un%20serveur%20de%20dev%0Afrankenphp%20php-server%20-r%20public%2F%0A%0A%23%20Acc%C3%A9der%20%C3%A0%20https%3A%2F%2Flocalhost%20%E2%80%94%20certificat%20HTTPS%20auto-g%C3%A9n%C3%A9r%C3%A9%20! » message= » » highlight= » » provider= »manual »/]
Le support Windows natif est très bien pour le développement. Mais en production, si le choix est possible, mieux vaut rester sur Linux. Le système de fichiers et le réseau de Linux offrent de meilleures performances en termes de débit. Pour ceux qui doivent rester sur Windows en production, FrankenPHP via WSL sera un peu plus rapide que le natif.
Dev Containers et la fin de la galère d’installation
L’un des gros problèmes quand on arrive sur un nouveau projet, c’est la mise en place de l’environnement de développement : installer la bonne version de PHP, les bonnes extensions, configurer la base de données… Ça peut prendre des heures, parfois des jours.
Le projet Symfony Docker (maintenu par Kévin) supporte désormais les Dev Containers. C’est un standard qui permet de décrire tout l’environnement de dev dans un fichier de configuration. On ouvre le projet dans son éditeur (VS Code, PhpStorm, GitHub Codespaces, ou même Emacs), et tout s’installe et se configure automatiquement.
Xdebug opérationnel sans configuration
Autre bon point : Xdebug (l’outil de débogage pas-à-pas en PHP, l’équivalent des breakpoints de Chrome DevTools mais pour le back-end) est préinstallé et configuré pour fonctionner immédiatement. On ouvre le projet, on pose un breakpoint, ça marche. Même avec le Mode Worker activé.
Ceux qui ont déjà essayé de configurer Xdebug avec Docker et PHP-FPM savent à quel point c’est laborieux. Ici, zéro configuration nécessaire.
Coder avec l’IA dans un bac à sable
Le moment fort de la démo, c’est quand Kévin a montré un agent Claude Code (l’outil IA en ligne de commande d’Anthropic) en train de coder dans le projet Symfony en live, contrôlé depuis son téléphone.
Pourquoi c’est un sujet ?
Les agents de codage IA ont besoin d’exécuter des commandes sur la machine : installer des packages, lancer des tests, modifier des fichiers… Sans restriction, ils pourraient en théorie accéder à n’importe quoi sur le système.
Un conteneur avec firewall
Symfony Docker embarque maintenant un mode dédié aux agents IA. L’agent tourne dans le conteneur Docker avec un firewall strict et une allowlist limitée aux domaines essentiels (Packagist, GitHub…). L’agent peut installer des dépendances, exécuter des tests et modifier des fichiers, mais ne peut pas envoyer de données vers un serveur non autorisé.
La configuration est détaillée dans la documentation dédiée aux agents dans le dépôt Symfony Docker.
Les Sidekicks : des tâches de fond en continu
Kévin a présenté ce concept comme une suite logique de ce que FrankenPHP rend possible.
En PHP classique, tout est lié au cycle requête/réponse : un utilisateur envoie une requête, PHP traite, renvoie une réponse, et c’est fini. Pas de processus qui tourne en permanence en arrière-plan.
Avec FrankenPHP, on peut lancer des workers PHP qui tournent en continu, en dehors du cycle HTTP. Ce sont les sidekicks : des tâches de fond spécialisées qui surveillent l’environnement et reconfigurent l’application en temps réel, sans polling, sans redéploiement. Le pattern a été détaillé dans un talk dédié au SymfonyLive.
Ce que ça donne en production
Images Docker rootless
Les images Docker fournies par Symfony Docker sont maintenant rootless par défaut. Le processus à l’intérieur du conteneur ne tourne plus en tant que root. Si un attaquant exploite une faille, ses droits sur le système sont très limités. Une bonne pratique de sécurité désormais appliquée d’office.
Performances
D’après les benchmarks réalisés avec Tideways (un profiler PHP), FrankenPHP est déjà plus rapide que PHP-FPM en mode classique. Avec le Mode Worker, l’écart se creuse.
| Nginx + PHP-FPM | FrankenPHP classique | FrankenPHP Worker | |
| Démarrage par requête | Tout est rechargé | Tout est rechargé (optimisé) | Une seule fois |
| HTTPS | Config manuelle | Automatique | Automatique |
| HTTP/2 & HTTP/3 | Partiel | Natif | Natif |
| Temps réel | Infra externe nécessaire | Mercure intégré | Mercure intégré |
| Hot Reload en dev | Non | Oui | Oui |
| Early Hints (103) | Non | Oui | Oui |
Logs structurés
FrankenPHP ajoute une fonction PHP pour écrire des logs propres et structurés en JSON. Voici les exemples de la doc officielle :
[pastacode lang= »markup » manual= »%3C%3Fphp%0A%0A%2F%2F%20Log%20a%20simple%20informational%20message%0Afrankenphp_log(%22Hello%20from%20FrankenPHP!%22)%3B%0A%0A%2F%2F%20Log%20a%20warning%20with%20context%20data%0Afrankenphp_log(%0A%20%20%20%20%22Memory%20usage%20high%22%2C%0A%20%20%20%20FRANKENPHP_LOG_LEVEL_WARN%2C%0A%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20’current_usage’%20%3D%3E%20memory_get_usage()%2C%0A%20%20%20%20%20%20%20%20’peak_usage’%20%3D%3E%20memory_get_peak_usage()%2C%0A%20%20%20%20%5D%2C%0A)%3B » message= » » highlight= » » provider= »manual »/]
Ça produit des logs JSON sur la sortie standard :
[pastacode lang= »markup » manual= »%7B%22level%22%3A%22info%22%2C%22ts%22%3A1704067200%2C%22logger%22%3A%22frankenphp%22%2C%22msg%22%3A%22Hello%20from%20FrankenPHP!%22%7D%0A%7B%22level%22%3A%22warn%22%2C%22ts%22%3A1704067200%2C%22logger%22%3A%22frankenphp%22%2C%22msg%22%3A%22Memory%20usage%20high%22%2C%22current_usage%22%3A10485760%2C%22peak_usage%22%3A12582912%7D » message= » » highlight= » » provider= »manual »/]
C’est pratique parce que les logs JSON sont faciles à traiter par des outils de monitoring comme Datadog, Grafana Loki, ou Elastic.
Migrer vers FrankenPHP
Option 1 : Symfony Docker (la plus simple)
La méthode recommandée. On clone le squelette, on lance Docker, et c’est prêt :
[pastacode lang= »bash » manual= »%23%20Cloner%20le%20squelette%0Agit%20clone%20https%3A%2F%2Fgithub.com%2Fdunglas%2Fsymfony-docker.git%20mon-projet%0Acd%20mon-projet%0A%0A%23%20Lancer%20l’environnement%20complet%0Adocker%20compose%20up%20-d%0A%0A%23%20C’est%20tout%20!%20Va%20sur%20https%3A%2F%2Flocalhost%0A%23%20HTTPS%20configur%C3%A9%20automatiquement%2C%20Hot%20Reload%20activ%C3%A9%2C%20Worker%20Mode%20op%C3%A9rationnel » message= » » highlight= » » provider= »manual »/]
Pour un projet Symfony existant, il suffit de récupérer les fichiers Docker du squelette (Dockerfile, compose.yaml, dossier .devcontainer) et de les intégrer au projet.
Option 2 : Le binaire directement (sans Docker)
Pour ceux qui ne souhaitent pas utiliser Docker :
[pastacode lang= »bash » manual= »%23%20Installation%20(Linux%20%2F%20macOS)%0Acurl%20https%3A%2F%2Ffrankenphp.dev%2Finstall.sh%20%7C%20sh%0A%0A%23%20Lancer%20le%20serveur%20sur%20un%20projet%20existant%0Acd%20%2Fchemin%2Fvers%2Fmon-projet-symfony%0Afrankenphp%20php-server%20-r%20public%2F%0A%0A%23%20Avec%20le%20Mode%20Worker%0Afrankenphp%20php-server%20–worker%20public%2Findex.php%20–watch » message= » » highlight= » » provider= »manual »/]
Option 3 : Via le gestionnaire de paquets de ton OS
FrankenPHP est aussi installable via les gestionnaires de paquets classiques. Tout est détaillé dans la documentation officielle d’installation.
Ce qu’on peut en retenir
Une chronologie rapide
| Date | Événement |
| Octobre 2022 | Première version publique de FrankenPHP |
| Décembre 2025 | Version 1.11 — Hot Reload, logs structurés, améliorations de performance |
| 6 mars 2026 | Version 1.12 — Support natif Windows (3,6x plus rapide que Nginx/PHP-FPM sur Windows) |
| 26 mars 2026 | SymfonyLive Paris — Kévin montre Dev Containers, Xdebug intégré, agents IA sandboxés, Sidekicks |
| 2026+ | Sidekicks en bundles Symfony, intégration renforcée avec Symfony 8 |
Ma conclusion
Ce que cette conférence montre, c’est que FrankenPHP ne se limite pas à « un serveur PHP plus rapide ». C’est toute l’expérience de développement qui évolue :
- Plus de problème d’environnement : un
docker compose upet c’est prêt - Plus de F5 pour voir ses changements : le hot reload s’en occupe
- Plus besoin de WSL sur Windows : ça marche nativement
- L’IA intégrée de manière sécurisée : les agents de codage dans un bac à sable
- Des performances en production : sans effort supplémentaire
Avec Symfony 8 qui arrive et toutes les briques qui se mettent en place (le composant TUI, le composant AI, le JsonStreamer, le Scheduler…), l’écosystème PHP n’a probablement jamais été aussi dynamique.
Liens utiles
- Documentation officielle : frankenphp.dev
- Code source : github.com/php/frankenphp
- Symfony Docker : github.com/dunglas/symfony-docker
- Blog de Kévin Dunglas : dunglas.dev
- Article sur le support Windows : Windows Support for FrankenPHP: It’s Finally Alive!
- Article de Kévin post-SymfonyLive : Coding at the Speed of Thought