I know this is a pretty random post for my blog here which is primarily geared towards building a business online, but the other day I was working on some code & couldn’t for the life of me remember how to execute a PHP script in the background to stop it hanging the main page that the user was using…
Anyway long story short I finally managed to figure it out (with some help from StackOverflow) & so as a result I’ve decided to put a post together here explaining exactly how I did it – kinda for my own future reference, and well just in case any webmasters reading my blog happen to find themselves in a similar pickle.
So if you’re working on a project & you’re trying to figure out how to run PHP scripts in the background to stop the page from hanging & making the user wait – or if you’ve got a few projects already launched you might want to revisit with this new-found knowledge then keep reading & I’ll show you exactly how to do it. ?
Why My PHP Script Was Hanging…
Basically I’ve been spending a lot of time recently working on building a user portal, which (as you can probably guess) includes functions like user registration, user password reset – and a few account related emails.
Now over the years I’ve learned the very-hard way that using your own server to send mail is BAD news – especially through the mail() function (unless of course you’re just handling local mail).
But yeah, basically if you’re building anything that’s going to be allowing user registrations & firing out emails to a bunch of different 3rd party email providers then definitely do not use your own server to do that… Otherwise you’re just going to cause yourself a whole host of problems.
So to get around the problem of handling the mail myself I decided to use the services of Mailgun – and I have to give a shout-out here because as far as I’m concerned Mailgun have been freaking awesome.
However there is one problem that arises as a developer – which is that to send mail via a 3rd party you have to forward the request through their servers (likely through TLS)… And this takes time.
So picture this – a user is hopping around your website page to page & triggers an action that requires an email to be sent…
This could be the registration process itself, the forgot password process or something else… Whatever it is, all the while your server is busy forwarding the email on & then waiting for a response to see if it sent successfully the user has to sit & wait.
Now you could give them a nice AJAX spinner or something to look at but let’s face it, that’s lame. Nobody wants to look at spinners – this is 2019 and with the likes of Amazon Prime surfacing the world wants it, and the worlds want it now!
People these days have expectations of speed & every second that page hangs is another 3 tuts & hair pulls from the person waiting.
How Do We Run a PHP Script In The Background?
The answer of what you need to do to stop the script hanging is pretty obvious – you need to bundle up whatever is making it hang, put it in a different file & then run it in the background so it can be doing its thing whilst the user carries on enjoying the site…
But the execution is a little more difficult – especially to do it to the stage where the main PHP script will actually stop hanging.
You see running the script in the background itself (which we’ll be using the shell_exec function to do) is actually not enough. PHP has some funky quirks & even if you manage to run the script in the background the main page will still hang & wait.
Before I get onto that though, first – here’s the code to use shell_exec to run a script in the background:
shell_exec(“path/to/php /path/to/file/to/execute &”);
Pretty simple right? Nice one-liner – just include the path to PHP (which more often than not will be /usr/local/bin/php), the path to the file you want to execute – and importantly the & symbol & jobs a gooden’… You’ll have triggered a script to execute in the background using shell.
Now, the problem… The page still hangs!
Thankfully though after some frustration I managed to figure out why. Strangely it seems that if you want to execute the script in the background AND stop the primary page from hanging then you need to setup alerts – even if they’re disabled.
So if you actually want to log alerts then you’ll want to setup the code like this:
shell_exec(“path/to/php /path/to/file/to/execute ‘alert’ >> /path/to/data.log &”);
And if you don’t want alerts then you’ll need to set it up like this:
shell_exec(“path/to/php /path/to/file/to/execute ‘alert’ >> /dev/null &”);
At last that code will not only execute your PHP script in the background but it will also do it without making the primary page that it was executed from hang, making the user wait until it was complete.
Passing Variables To The Background PHP Script
It’s more than likely that you don’t just want any old script to run in the background, because if you did you’d likely just use a cron job to do it… The fact that you’re looking specifically to run a PHP script in the background from a manual trigger says to me that you likely want to pass some variables to it…
For example in the instance of a password reset email you’d need to pass the ID of the users password to reset, then the “background file” would pull the users email from the database using the given ID & fire off the email as required…
But how do you pass variables through a shell_exec command?
Thankfully it’s pretty easy – you just add them between the path of the file you wish to execute & the alert command like so:
shell_exec(“path/to/php /path/to/file/to/execute ‘”.$variable1.”‘ ‘”.$variable2.”‘ ‘alert’ >> /dev/null &”);
As far as I’m aware you can add as many as you like – though I haven’t tried it, and personally for this type of background-running script I couldn’t really see the need for submitting more than a handful of variables at most.
Now the bigger question – how do you collect the variables on the other side?
If you’ve already made any attempt at this you’ll likely have came to realize that $_GET and $_POST don’t work – so how the heck do you pull the variables passed to a file through shell_exec? What’s the secret?
Simple – use $argv.
So in the instance of our example above where we passed $variable1 & $variable2, to collect those on the other side we’d use $argv & $argv.
Note: $argv will simply give you the name of the file – variables start at . ?
Anyway Yeah, That’s How It’s Done!
Like I said at the start of this post, it’s totally random I know – and certainly a lot different from the usual type of content I publish here on my blog but honestly I just think this is a pretty darn important snippet of code & I wanted to make sure I noted it for future reference so figured why not post it here to help others out too.
So if you’ve happened to stumble across this post from a search engine or somewhere & you too were struggling with the same problem like me then I hope what I’ve wrote here has helped you to get it sorted.
And of course as always if you do happen to have any questions don’t hesitate to leave them below & I’ll do my best to get back to you as soon as I can. ?