Photo by Compare Fibre on Unsplash

PHP Fibers: How PHP is Finally Warming Up to Asynchronous Programming

Byte Blog

--

Ah, PHP. For years, it was the go-to language for web development, powering everything from tiny blog sites to giant platforms like Facebook (at least in its early days). But despite all its growth, PHP always had a somewhat conservative approach to asynchronous programming – until now. With the arrival of PHP Fibers in PHP 8.1 (and a much-needed tune-up in PHP 8.4), it seems PHP is finally embracing the joys of concurrency.

So, let’s take a deep dive into PHP Fibers: what they are, how they work, and why you might find yourself grinning as you introduce them into your codebase.

What Exactly are Fibers, and Why Should You Care?

Think of fibers as lightweight threads – they let you pause and resume functions without blocking your whole application. Imagine you’re in a line at the coffee shop, ordering a latte. While you’re waiting, instead of just standing there doing nothing, you could pause your order and check your emails or chat with a friend. When your latte’s ready, you jump back into the ordering process without missing a beat.

In code, fibers allow your application to keep doing useful work while waiting for time-consuming tasks to finish. Unlike traditional synchronous PHP code, where everything runs in a single line (one command after another, no skipping ahead), fibers let you jump in and out of tasks – perfect for real-time applications that can’t afford to hang around.

Important Note on Versions: Fibers were introduced in PHP 8.1, but they’re fully functional and more stable in PHP 8.4. So if you’re still on PHP 7.x or 8.0, now might be the time for an upgrade.

Why Fibers? Didn’t PHP Already Have Asynchronous Options?

You might be thinking, “But wait! Haven’t we had options like pcntl_fork and ReactPHP for concurrency?” And you’d be right. But these methods are either complex or require additional extensions and libraries. Plus, they don’t let you write asynchronous code as naturally as fibers do.

With fibers, you don’t have to jump through hoops or install extra extensions. Just write your code, sprinkle in some fibers, and you’re good to go.

Getting Started with PHP Fibers

Now, let’s have a play with some code and get a feel for how fibers work. First, let’s check if your PHP version is ready for the fiber revolution:

php -v

If you see PHP 8.1 or higher, you’re all set! If not, well, time to talk to whoever is managing your server or, in extreme cases, brace yourself for the great migration.

The Basic Anatomy of a Fiber

The beauty of PHP Fibers is in their simplicity. Here’s how to create a fiber and get it up and running:

$fiber = new Fiber(function() {
echo "Fiber started…\n";
Fiber::suspend(); // Pause the fiber
echo "Fiber resumed…\n";
});
echo "Fiber starting…\n";
$fiber->start(); // Start the fiber
echo "Main script running…\n";
$fiber->resume(); // Resume the fiber

Here’s what’s going on:

1. We create a new Fiber with a function that does two things: prints a message, suspends itself, then prints another message.

2. We start the fiber, which begins execution until it hits Fiber::suspend().

3. The fiber “pauses” itself at Fiber::suspend(), allowing the main script to keep going.

4. Later, we call $fiber->resume(), which picks up the fiber where it left off and finishes the job.

And voilà! You’ve just created asynchronous code in PHP.

A Practical Example: Fetching Data with Fibers

Now let’s see something a bit more useful. Imagine you need to fetch data from multiple APIs, but you don’t want to wait for each request to finish before moving on to the next. Here’s where fibers can shine:

function fetchData($url) {
return new Fiber(function() use ($url) {
echo "Fetching from $url...\n";
sleep(2); // Simulate network delay
echo "Data from $url fetched.\n";
});
}

$fiber1 = fetchData('https://jsonplaceholder.typicode.com/posts/1');
$fiber2 = fetchData('https://jsonplaceholder.typicode.com/posts/2');

$fiber1->start();
$fiber2->start();

echo "Doing other things while data is being fetched...\n";

// Resume fibers once we're ready for the data
$fiber1->resume();
$fiber2->resume();

This code essentially sets up two fibers, each fetching data from a different URL. While they “wait” (simulated here with sleep(2)), your main script can do other tasks. Once it’s ready to use the data, it resumes the fibers.

This might look a little odd at first, but imagine the possibilities… you could be working on other parts of your application (like rendering a page or handling user input) while data is fetched in the background.

Real-World Use Case: Asynchronous Image Processing

Let’s take it a step further. Imagine you have an application where users can upload images, and you want to apply several filters to those images. Processing each filter can take a bit of time, so let’s use fibers to handle it all in the background:

function applyFilter($image, $filter) {
return new Fiber(function() use ($image, $filter) {
echo "Applying $filter to $image...\n";
sleep(2); // Simulate filter processing
echo "$filter applied to $image.\n";
});
}

$image = 'user-uploaded-image.jpg';
$filters = ['grayscale', 'blur', 'sharpen'];

// Create a fiber for each filter
$fibers = array_map(fn($filter) => applyFilter($image, $filter), $filters);

// Start all fibers
foreach ($fibers as $fiber) {
$fiber->start();
}

echo "Processing other tasks while filters are being applied...\n";

// Resume each fiber to complete processing
foreach ($fibers as $fiber) {
$fiber->resume();
}

This example uses fibers to apply three different filters to an image concurrently. While the filters are applied, the script can move on and “process other tasks.” When we’re ready, we resume each fiber to complete the filtering process.

PHP 8.4 and Beyond: What’s Next for Fibers?

While fibers in PHP 8.1 were an exciting start, PHP 8.4 brings several improvements that make them more stable and efficient for production use. Version 8.4 fixes some issues around fiber memory management and concurrency handling, making fibers more predictable and robust.

If you’re diving into PHP asynchronous programming, using PHP 8.4 will provide a smoother experience. It’s worth mentioning that fibers are a low-level feature – if you’re building complex applications, consider using a higher-level library (like ReactPHP) that can abstract some of the details and offer additional tools for managing concurrency.

A Word of Caution

Fibers are a powerful tool, but with great power comes great responsibility. It’s easy to go a little fiber-crazy and start pausing and resuming everything. But overuse can make your code hard to read and debug, so use fibers wisely. And remember: fiber usage is like juggling flaming swords – exciting, but best attempted with a solid grasp of the basics.

Wrapping It Up

PHP Fibers are a great addition for PHP developers who’ve long wished for a simpler way to handle asynchronous programming. They provide a clear, manageable way to work with concurrency, without the complexities of threads or external libraries. From asynchronous API calls to background processing, fibers open up a world of possibilities in PHP – making it more modern, capable, and just a little bit more fun.

So, if you’re on PHP 8.1 or higher, give fibers a spin in your next project. They might just become your new favourite feature!

--

--