The Synchronous Bottleneck
For decades, PHP developers have been trapped in a sequential world. If you needed to check the status of 50 different websites, you had to wait for the first one to finish before starting the second. If site #5 was slow, your entire script ground to a halt. This is fine for simple web requests, but for background tasks and CLI tools, it is a massive waste of resources.
PHP 8.1 introduced Fibers, a way to handle concurrency without the complexity of full-blown multi-threading or the overhead of external libraries. Fibers allow you to pause a function and resume it later, which is perfect for I/O-bound tasks like fetching remote URLs.
The Multi-Site Health Checker
Imagine you are managing a fleet of microservices. You need a tool that pings each service and reports if any are down. Instead of checking them one by one, we can use Fibers to start multiple requests and process whichever one finishes first.
Here is a simplified example of how you can wrap a slow I/O operation in a Fiber:
class SiteChecker {
public function check(string $url): void {
$fiber = new Fiber(function() use ($url): void {
$start = microtime(true);
// Simulating a non-blocking network call
$status = $this->fetchStatus($url);
$end = microtime(true);
echo "URL: $url | Status: $status | Time: " . round($end - $start, 4) . "s\n";
});
$fiber->start();
}
private function fetchStatus(string $url): int {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return $code;
}
}Managing Concurrency with an Event Loop
While the example above starts a Fiber, it doesn't truly leverage concurrency until you manage a collection of them. To make this practical, you need a simple scheduler that checks if Fibers have finished their work. In a real-world scenario, you would use a non-blocking stream select, but even a basic loop demonstrates the power of the concept.
$sites = [
"https://google.com",
"https://github.com",
"https://php.net",
"https://invalid-site-test.com"
];
$fibers = [];
$checker = new SiteChecker();
foreach ($sites as $site) {
$fibers[] = new Fiber(fn() => $checker->check($site));
}
// Start all fibers
foreach ($fibers as $fiber) {
$fiber->start();
}
echo "All checks initiated concurrently!\n";Why This Matters for Modern PHP
Fibers are not about making PHP faster at math; they are about making PHP better at waiting. When your script spends 90% of its time waiting for a database query or an API response, Fibers allow the CPU to do something else in the meantime. This is the foundation for high-performance PHP engines like Swoole or RoadRunner, but now it is available in the core language.
By using Fibers, you can build scrapers, deployment tools, and data aggregators that perform significantly better than their procedural ancestors. You stop being limited by the slowest external server and start being limited only by your local resources.


