background processes in php

so you’ve just built a fantastic processing routine for your application.

you’ve checked and double checked the integrity of user input, and you’re doing some serious processing. there’s only one problem: it’s too slow.

there’s a simple solution: forking your processing script, and running the code as a background process asynchronously. it can email your user when it’s done: they’ll wait. in this tutorial, i’ll show you how to get started with background processes in php.

when we want some kind of background process running our php code, we have a simple challenge: we can’t leave it up to the client. on the web, people hit their stop button, their browsers lock up and they force quit, they even have the odd power outage. when we want to do complex processing on the server side, we need to detach from the client-server model of a web-served script. php can fork a script, but the parent script is still facing an unreliable client.

our best option, then, is to launch a background process from the command line. there are three steps to this: starting the background script, passing it information to do its job, and checking when it’s finished.


starting the background script

on unix systems, we can easily call another php script via the shell, set it to run off in the background and send its output to /dev/null. here’s a sample:

exec ("/usr/bin/php proc.php >/dev/null &");

here, we call the exec function; instructing it to run our local php binary – usually at /usr/bin/php or /usr/local/bin/php, check with your host/sysadmin. we pass it a single argument: the filename of the php script that handles our background process. we then send the output to /dev/null, effectively destroying it. the last character, the & symbol, is important – this tells the system to start this process in the background and to let us continue.


talking to the background process

it’s all very well to start a background process, but now it needs to know what to do. we handle this through command line arguments. let’s update the previous example:

exec ("/usr/bin/php proc.php --task=50 >/dev/null &");

our proc.php file might look like this:

running "php proc.php --task=50" on command line produces the following output:
handling process --task=50

from here, you can easily design your script to do what it needs to.


monitoring the background process

there’s just one last detail: how do we monitor the progress of our background process? it’s best to use an independent datastore that can be relied upon, instead of communicating with running threads – your application’s mysql database would be perfect. you can create a “sessions” or “jobs” table with an id column, a status column (started, in progress, finished – 0, 1, 2), and any other information you need. before you start your background process, create a new entry in this table and check the insert id, then pass it to the background process when you start it:

 exec (“/usr/bin/php proc.php –some_info=50 –job=1234 >/dev/null &”);

your proc.php file can then update the table row with the id you supply it, and your front end applications can provide status updates to end users by checking up on all pending jobs for the current user – relatively straightforward business logic.

if you’re going to be running many background processes, a job queue and an “always-on” script running on your server may also be an option. in this case, consider looking into pcntl_fork() and the program execution functions.