Introduction à la programmation asynchrone en PHP
\n\nLe PHP traditionnel fonctionne de manière synchrone : chaque opération s'exécute séquentiellement. Si un script doit envoyer une requête HTTP ou lire un fichier, il attend la fin de l'opération, bloquant l'exécution de tout le code. Pour les applications web à forte charge, cela devient un goulot d'étranglement. La programmation asynchrone résout ce problème en permettant d'exécuter plusieurs tâches simultanément sans bloquer le thread principal.
\n\nDans ce guide, nous allons voir comment fonctionne l'asynchrone en PHP, quels outils sont disponibles et comment les utiliser en pratique. Vous découvrirez les générateurs, les bibliothèques ReactPHP et Swoole, ainsi que les nouvelles fonctionnalités de PHP 8.1 — Fiber.
\n\nFondamentaux de la programmation asynchrone
\n\nQu'est-ce que l'asynchrone et pourquoi en a-t-on besoin ?
\n\nImaginez que vous préparez le petit-déjeuner. Approche synchrone : vous mettez la bouilloire, attendez qu'elle bout, puis commencez à faire frire les œufs. Approche asynchrone : vous mettez la bouilloire et, pendant que l'eau chauffe, vous préparez les œufs en parallèle. En PHP, cela signifie qu'au lieu d'attendre une réponse d'une base de données ou d'une API externe, vous pouvez exécuter un autre code.
\n\nLes principaux avantages de l'approche asynchrone :
\n- \n
- Amélioration des performances lors des opérations d'E/S (réseau, disques, bases de données) \n
- Économie de ressources serveur — moins de threads traitent plus de requêtes \n
- Possibilité de créer du temps réel (chats, notifications, streaming) \n
Le problème du code synchrone
\n\nConsidérons un exemple classique : la récupération de données depuis deux API distantes. Le code synchrone s'exécutera séquentiellement :
\n\n<?php\nfunction fetchData($url) {\n $ch = curl_init($url);\n curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\n $result = curl_exec($ch); // Blocage pendant la requête\n curl_close($ch);\n return $result;\n}\n\n$start = microtime(true);\n$data1 = fetchData('https://api.example.com/users');\n$data2 = fetchData('https://api.example.com/posts');\necho "Temps : " . (microtime(true) - $start);\n?>\n\nSi chaque requête prend 2 secondes, le temps d'exécution total sera de 4 secondes, alors que nous pourrions exécuter les requêtes en parallèle.
\n\nOutils pour l'asynchrone en PHP
\n\n1. Générateurs (yield) — asynchrone légère
\n\nLes générateurs sont apparus dans PHP 5.5 et permettent de créer des fonctions qui peuvent suspendre leur exécution et rendre le contrôle au code appelant. C'est la base pour créer des coroutines.
\n\n<?php\nfunction generator() {\n echo "Début du générateur\\n";\n yield 1;\n echo "Après le premier yield\\n";\n yield 2;\n echo "Fin\\n";\n}\n\n$gen = generator();\nforeach ($gen as $value) {\n echo "Reçu : $value\\n";\n}\n?>\n\nLes générateurs peuvent être utilisés pour organiser des opérations non bloquantes en combinaison avec une boucle d'événements. Cependant, pour une asynchrone complète, cela ne suffit pas — une bibliothèque est nécessaire.
\n\n2. ReactPHP — bibliothèque orientée événements
\n\nReactPHP est une bibliothèque populaire pour la programmation asynchrone. Elle fournit une boucle d'événements (Event Loop), des sockets non bloquants, un client et un serveur HTTP. Installation via Composer :
\n\ncomposer require react/event-loop react/http\n\nExemple de requête HTTP asynchrone :
\n\n<?php\nrequire 'vendor/autoload.php';\n\nuse React\\EventLoop\\Factory;\nuse React\\HttpClient\\Client;\nuse React\\HttpClient\\Response;\n\n$loop = Factory::create();\n$client = new Client($loop);\n\n$request = $client->request('GET', 'https://api.example.com/data');\n$request->on('response', function (Response $response) {\n $response->on('data', function ($chunk) {\n echo "Fragment reçu : " . strlen($chunk) . " octets\\n";\n });\n $response->on('end', function () {\n echo "Requête terminée\\n";\n });\n});\n$request->end();\n\necho "Requête envoyée, attente...\\n";\n$loop->run();\n?>