phasync
use phasync\Services\CurlAwaiter;
function fetch(string $url): string
{
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// Inside a coroutine this waits without blocking the others; outside, it just runs
return CurlAwaiter::await($ch);
}
$pages = phasync::run(function () {
$a = phasync::go(fn () => fetch('https://www.php.net/'));
$b = phasync::go(fn () => fetch('https://getcomposer.org/'));
return [phasync::await($a), phasync::await($b)];
});phasync, the extension, and Swerve#
phasync v2.0.2#
The coroutine library. go() and await() on PHP's own Fibers, with timeouts and cancellation. No promises.
- One
phasync::run()call is a complete program - Runs under PHP-FPM, the CLI, or Swerve
composer require phasync/phasync
ext-phasync v2.0.0#
The optional extension. PDO, mysqli, curl, file I/O and sleep() become cooperative inside a coroutine instead of blocking the worker — no rewrite.
- Epoll instead of
stream_select() - Bundles the
Scopeclass, the per-request identity that request-scoped state is keyed on
Start with phasync alone inside an application you already run under PHP-FPM, to overlap one function's own API calls or queries. Reach for Swerve when you want every request handled concurrently, not only that one function.
phasync and fiber-interop#
fiber-interop is a shared concurrency API (fiber\go(), fiber\await() and the rest) that runs unchanged on phasync, Revolt, AMPHP, ReactPHP, Swoole or TrueAsync, picked by installing one adapter package. The fiber-interop/phasync adapter runs it on phasync's event loop. fiber-interop's own adapter guide names phasync as the one to start with if you have no event loop of your own yet, calling it "a complete runtime with nothing else to configure". A library written against fiber-interop/api runs on phasync without depending on it directly.