PHP has long been known as a synchronous, blocking language where code executes line by line. For most traditional web applications, this has been sufficient. However, as applications grow more complex - handling concurrent I/O, integrating with APIs, managing streams, and executing parallel tasks - the need for structured concurrency within PHP has become more apparent.
That's where Fibers come in. Introduced in PHP 8.1, Fibers bring cooperative multitasking to the language, making it possible to write asynchronous and concurrent code in a much more natural way.
What Are Fibers?
A Fiber is a lightweight, interruptible unit of execution. You can think of it as a mechanism that allows you to pause and resume blocks of code without losing their state.
Fibers are not threads - they don't run in parallel. Instead, they provide a way to suspend execution in the middle of a function and later resume it, much like generators but more flexible.
Key difference with generators:
Why Do We Need Fibers?
Without Fibers, writing asynchronous code in PHP often relies on callbacks or promises. This leads to deeply nested, hard-to-read code (sometimes called "callback hell"). Fibers allow developers to flatten asynchronous code so it looks synchronous, even though it's non-blocking under the hood.
They make it possible to build event loops and async frameworks (like amphp or ReactPHP) in a cleaner way.
How Fibers Work
Here's the basic lifecycle of a Fiber:
1. Create a Fiber with a callable (function).
2. Start it using ->start(). The fiber runs until it either finishes or suspends.
3. Suspend execution within the fiber using Fiber::suspend(). Control returns to the caller.
4. Resume the fiber with ->resume(). Execution continues where it left off.
Example: A Simple Fiber
$fiber = new Fiber(function (): void { echo "Fiber started"; $value = Fiber::suspend("Paused at step 1"); echo "Fiber resumed with: $value"; Fiber::suspend("Paused at step 2"); echo "Fiber finished"; }); echo $fiber->start(); // Starts the fiber, prints "Fiber started" // Suspends and returns "Paused at step 1" echo $fiber->resume("Resuming after 1"); // Resumes with given value // Prints "Fiber resumed with: Resuming after 1 Paused at step 2" echo $fiber->resume(); // Resumes again // Prints "Fiber finished"
Error Handling in Fibers
Fibers can also throw exceptions into suspended execution, allowing for robust error handling:
$fiber = new Fiber(function () { try { Fiber::suspend(); } catch (Throwable $e) { echo "Caught inside fiber: " . $e->getMessage(); } }); $fiber->start(); $fiber->throw(new Exception("Something went wrong")); // Caught inside fiber: Something went wrong
Fibers in Asynchronous PHP
Fibers alone don't make PHP asynchronous, but they enable libraries to provide async I/O with a synchronous-like syntax.
For example, instead of writing:
$http->request('GET', 'https://api.example.com', function ($response) { $db->query('INSERT INTO logs ...', function () { echo "Done!"; }); });
You could write:
$response = $http->request('GET', 'https://api.example.com'); $db->query('INSERT INTO logs ...'); echo "Done!";
Under the hood, Fibers are suspending and resuming execution as I/O operations complete, but the code looks synchronous.
Fibers are one of the most exciting additions to PHP in years. They bring a new level of control over execution flow, making async code easier to write, read, and maintain.
While they don't replace threads or processes, Fibers empower PHP developers to build modern, non-blocking applications with structured concurrency. Combined with async frameworks, they unlock possibilities for high-performance PHP applications that were previously difficult to achieve.
Source: Orkhan Alishov's notes