ReactPHP

ReactPHP: Event Loop, Promises and HTTP

ReactPHP (https://github.com/reactphp 29 ) is a set of small packages: on 23 September 2026, composer require react/http react/async installed react/event-loop 1.6.0, react/http 1.11.1, react/promise 3.3.0 and react/async 4.3.0. The global Loop runs when the script ends, and code that must wait returns a promise that settles later:

react-server.php: an HTTP server and a periodic timer in one processPHP
<?php
require __DIR__ . '/vendor/autoload.php';
use React\EventLoop\Loop;
use React\Http\Message\Response;
$hits = 0;
$http = new React\Http\HttpServer(function ($request) use (&$hits) {
  $n = ++$hits;
  $ms = (int) ($request->getQueryParams()['ms'] ?? 0);
  $reply = Response::plaintext("request $n waited $ms ms, pid " . getmypid() . "\n");
  return new React\Promise\Promise(             // settle later, from a timer: nothing blocks
    fn ($resolve) => Loop::addTimer($ms / 1000, fn () => $resolve($reply)));
});
$http->listen(new React\Socket\SocketServer('127.0.0.1:8223'));
Loop::addPeriodicTimer(0.5, function () use (&$hits) { echo "tick: $hits requests\n"; });
Four concurrent requests against itShell
php react-server.php & server=$!; sleep 0.3
TIMEFORMAT='all four took %R s'; time seq 4 | xargs -P4 -I{} curl -s "127.0.0.1:8223/?ms=800"
sleep 0.2; kill $server
Output
tick: 4 requests
tick: 4 requests
request 1 waited 800 ms, pid 12034
request 2 waited 800 ms, pid 12034
request 3 waited 800 ms, pid 12034
request 4 waited 800 ms, pid 12034
all four took 0.831 s

One PID answered four 800 ms requests in 0.83 s while its timer ticked; PHP-FPM would need four workers. But one sleep() or PDO call stalls every connection, so use async packages such as react/mysql, and run the server under systemd 142,543 (Processes and Monitoring) behind Apache 129 (Apache).