Event Loops in PHP - A Feature Worth Exploring

As a PHP developer, you always have to wait. Then be it the wait for requests to remote services. Or the wait for databases to return rows from a complex query.

Doing other things while all this waiting can be a good idea.

Those of you who have written some JS, are probably familiar with callbacks and DOM events. There are callbacks in PHP too, but they do not work in the same way owing to a feature called the "event loop".

Let's throw some light on how the event loop works and how it can be used in PHP. We will explore some interesting PHP libraries. There might be some of you who will counter that "these are not yet stable enough to use in production". Others may have the opinion that these examples presented are "better in more mature languages". However, these reasons should not be good enough not to try them. You may also want to avoid these things in production. Our purpose is to highlight what is possible in PHP.

Where things go to wait:

To find out all about event loops, we must first take a look into how they work in a browser. Let's see this example:

Stylesheet:

<style>
	.welcome-screen{width: 500px; height: 300px;}
</style>

HTML:

<div class="welcome-popup"></div>

Script:

function fitToScreen(selector) {
    var element = document.querySelector(selector);
 
    var width = element.offsetWidth;
    var height = element.offsetHeight;
 
    var top = "-" + (height / 2) + "px";
    var left = "-" + (width / 2) + "px";
 
    var ratio = getRatio(width, height);
 
    setStyles(element, {
        "position": "absolute",
        "left": "50%",
        "top": "50%",
        "margin": top + " 0 0 " + left,
        "transform": "scale(" + ratio + ", " + ratio + ")"
    });
}
 
function getRatio(width, height) {
    return Math.min(
        document.body.offsetWidth / width,
        document.body.offsetHeight / height
    );
}
 
function setStyles(element, styles) {
    for (var key in styles) {
        if (element.style.hasOwnProperty(key)) {
            element.style[key] = styles[key];
        }
    }
}
 
fitToScreen(".welcome-popup");

Output:

Welcome Popup

In the above program, you will see that it requires no extra libraries. All you have to do is to select any browser that provides support for CSS scale transformations, and it will work in that. However, you must make sure that the CSS selector resembles an element in your document.

The new functions take a CSS selector and scale the element to fit the screen.

PHP uses a stack to store context, in this manner. Browsers take a step further and provide WebAPIs for things like Ajax callbacks and DOM events. JavaScript, is every bit as asynchronous as PHP in the sense that: they are single threaded, yet both look like they can do many things at once. But, in reality JS and PHP can do only one thing at the same time.

However, with the browser WebAPIs, (stuff like setTimeout and addEventListener) we can designate parallel work to different threads. When such an event takes place, browsers simply add the callbacks to the "callback queue". But, when the stack is empty, browsers tend to execute the callbacks that it picked up from the callback queue.

The above mentioned process that helps make the stack empty followed by the callback queue, is known as the event loop.

How are things like, without an event loop?

You can run this code in JavaScript

setTimeout(function() {
    console.log("inside the set timeout");
}, 1);
 
console.log("outside the set timeout");

As you run this code, you will see "outside the set timeout", and then "inside the set timeout" within the console. The setTimeout function is, basically, a part of the WebAPIs that browsers provide to coders to work with. When the set time interval of 1 millisecond is passed, the callback is being added to the callback queue.

The second statement in the console.log completes first, when the statement inside the setTimeout gets started. In standard PHP, we don’t have anything like setTimeout. However, you can try and simulate that function as follows:

function setTimeout(callable $callback, $delay) {
    $now = microtime(true);
    while (true) {
        if (microtime(true) - $now > $delay) {
            $callback();
            return;
        }
    }
}
 
setTimeout(function() {
    print "inside the set timeout";
}, 1);
 
print "outside the set timeout";
 
================================
Output after 1 second timeout:
 
inside the set timeout
outside the set timeout
 

On running the above code, you'll see that the 'inside the set timeout' appears first and then the 'outside the set timeout' becomes visible. This is because we will have to execute the callback function after certain time delay.

In order to make the code less clogging, you may be tempted to move the while loop outside the setTimeout function and may add all your code inside that function. But, somewhat later, you most likely will be blocked by the loop again. And at some moment, you'll probably come to see how you can work on just a single thing in a single thread at once.

There are some ambiguous ways to implement non-blocking code in pace with event loops. You can use functions such as stream_select to create non-blocking network IO. Otherwise you can use C extensions like EIO to create non-blocking file system code. Most importantly, you can make use of two of the most important reactive component libraries for implementation of event loop, such as Icicle and React PHP. Let us have a quick glance at both these libraries:

Icicle

This library was created for implementing even loop. This is why Icicle helps implement the event loop in an excellent manner. The library uses “generators” for producing code that looks beautiful. The generators primarily are focused on easily writing asynchronous code that resembles synchronous code. You can produce non-blocking code, by combining generators together with the Promises feature of the Icicle library and an event loop.

React PHP

If you want to use a mature library than Icicle, then React PHP is exactly what you. It is not just a more mature option but also helps provide access to a larger variety of components for implementation of event loop. This reactive component library implements the event loop in the same way as the Icicle library, however, it doesn't use the generator stuff.

Let's Wrap Up!

We have been taught to have a single-threaded mindframe and it is extremely difficult to get out of it. If we had access to non-blocking APIs and event loops, we ourselves are not aware of the limits of code we could write. All PHP developers and the community in general must know of this architecture. One needs to learn, experiment and grow with asynchronous and parallel execution.

Last Word

Hope you have enjoyed reading this article on event loops in PHP. Please do write us if you have any suggestion/comment or come across any error on this page. Thanks for reading!

Article Author

Amanda Cline

is currently working for Xicom Technologies Ltd- a renowned PHP Development Outsourcing company. She has been an avid IT personnal with special interest in writing posts that serve as handy guide for individuals looking out to build a strong career in IT services and solutions sector.



Share this page on WhatsApp

Get Free Tutorials by Email

About the Author

is the founder and main contributor for cs-fundamentals.com. He is a software professional (post graduated from BITS-Pilani) and loves writing technical articles on programming and data structures.