Asynchronous PHP

Updated: Feb 12, 2020 — 1 min Read

PHP code is blocking, meaning that one block of code will not run until the block prior to it has finished. It wasn't built with asynchronous execution in mind like Go, NodeJs, and other languages.

Running asynchronous means you don't have to wait for something to happen before continue doing your thing. You send an email and go on with your life until you receive a response. You don't have to remain idle until the response comes back.

To achieve this on a web server, you can use different threads or different processes to take care of doing some work while your main thread continues doing other work. For example, sending a job to queue from your Laravel application allows you to hand the task to a worker process to take care of it while your main process does more work.

Threads vs. Processes

A process is a separate unit of execution, processes don't share resources with each other. However, a single process can start multiple threads, all threads share the same, or has access to, the same resources assigned to the process.

To cut it short, PHP's support for threading was introduced via a separate extension called pthreads. This extension is now archived.

Call stack and Event loop

Another way of achieving asynchronous execution is using an event loop. Think of an event loop as a worker that reads queued functions and executes it if the call stack is empty. A call stack is the normal synchronous flow of your program.

How to achieve asynchronous execution in php then?

use Symfony\Component\Process\Process;

$process = new Process(['php', 'artisan', 'task:run']);
$process2 = new Process(['php', 'artisan', 'anothertask:run']);

$process->start();
$process2->start();

// Do some work.

// Then we wait for the sub-processes to finish.
while ($process->isRunning() || $process2->isRunning()){
  sleep(1);
}

// Finally we return.
return response();

Using the code above, we start 2 subprocesses to run the task:run and anothertask:run artisan commands while we continue doing some work. Before we finish the execution of the parent process we wait for the child processes to finish.

That's a very simple implementation but I wanted to show you how easily it can be done. For more advanced use cases, Spatie has built a package called spatie/async which runs and manages several PHP processes to run your code in an asynchronous fashion.

Your main process starts multiple subprocesses and watches over them while it continues doing its own thing. It uses PHP's async signals to manage communication between the parent process and its children.

If you want to learn more on how this package works, check this post by Brent Roose where he explains how it works behind the curtains.

By Mohamed Said

Hello! I'm a full-stack web developer working at Laravel. In this publication, I share everything I know about Laravel's core, packages, and tools.

You can find me on Twitter and Github.

Join the mailing list

If you like this article, you may want to consider joining the mailing list to receive new content once it is posted.
This site was built using Wink. Follow the RSS Feed.