Blog

Run a PHP script in the background with AJAX & YUI

There are times when you want to run a PHP script in the background, something that is triggered by a user, but you don’t want them to have to wait for it to complete. A couple ways to accomplish this, but I’ll focus on one in particular. That’s making an asynchronous call using AJAX.

It’s pretty simple actually. The first thing is in your script that you want to run in the background, you need to make sure it runs long enough to complete, and that also it won’t die when the connection is aborted. So, at the top of this PHP script, you’ll want to add these 2 lines:

Now for how to actually get that script running in the background. We’ll be using javascript and taking advantage of the YUI library since it makes it particularly easy.

Basically, what happens is an async call is made to the script, and then the connection is aborted, so the script continues to run and the user can go on doing whatever they want. The key is you don’t want to abort the connection too fast. If it’s aborted right after it’s made the script won’t even have time to start. So, we need to give it a couple seconds before actually aborting. Here’s the javascript for this:

[javascript]
<script src="http://yui.yahooapis.com/2.8.0r4/build/yahoo/yahoo-min.js"></script>
<script src="http://yui.yahooapis.com/2.8.0r4/build/event/event-min.js"></script>
<script src="http://yui.yahooapis.com/2.8.0r4/build/connection/connection_core-min.js"></script>
<script type="text/javascript">
var spawnCallback = {
success: function(o) {
},
failure: function(o) {
},
timeout: 2000
};

function spawnProcess() {
YAHOO.util.Connect.asyncRequest(‘GET’,'url/to/script.php’,spawnCallback);
}
</script>
[/javascript]

And that’s about it. Then you just need to call the spawnProcess() function and it will trigger your designated PHP script which will run in the background until finished.

Tags: , , ,

5 Responses to “Run a PHP script in the background with AJAX & YUI”

  1. David P. says:

    It would be better to use popen() in your PHP script that “forks” off a new process. For example,

    pclose(popen(‘/usr/bin/php /path/to/something.php > /dev/null &’, ‘r’)

    (the redirection to /dev/null ensures that PHP won’t wait for any output, otherwise the call to popen() will still hang)

    Then the calling PHP script would have an opportunity to, e.g., generate some sort of job ID which it could be returned to the client that the JavaScript code could then use to query the server about the job’s status.

    More importantly this eliminates the race-condition of having to wait just long enough before aborting the ajax call. Yes once the php script gets called an abort won’t affect it because of the call to ignore_user_abort(1) but let’s say the user has some really nasty latency, then the couple of seconds wait might not be enough.

    Even if that happens in only 1% of your users it’s a bad design. Especially when a simple popen() call solves it.

    • Rick says:

      Thanks for the comments.

      There are definitely other ways to tackle this, with popen being one of them which I normally use when possible. But there are some setups where you can’t access PHP directly through a cli method and you’re restricted to accessing it through HTTP. This is more of a fallback solution for those cases.

      I should note that I created this for exactly that issue. One of our programs needs to have jobs that need to run every so often. We can’t use cron and we can’t use a popen call. So we had to come up with a workaround. This works as there is enough logic in place that if it doesn’t get fired off by a particular user due to latency, it will get fired off by another.

      I should adjust the original post and give some warning on this if it’s a mission critical situation where it gets fired off by a particular user even if they have high latency.

      • David P. says:

        Good points. You’re absolutely right about the situation in which the hosting provider doesn’t allow access to CLI etc. For me, I’d move to a different hosting provider in that case. :) But I realize not everyone has that option all the time.

  2. Julio says:

    Hi Rick,

    Thanks for this very useful trick, it works perfectly for me… almost all the time. I’m using it in a very small and simple application that works fine in all the browsers but IE. I didn’t find incompatibilities between YUI and IE, so….

    Any clue?

    Regards

    • Rick says:

      If IE isn’t given the dreaded little javascript error symbol, then the first thing I’d do is check the webserver access logs and see if the background script is being called at all, to make sure it’s at least making it that far.

Leave a Reply