Mala
Mala

Reputation: 14843

ignore_user_abort and redirect in php?

I have a very similar setup to the person here:
PHP Background Processes
i.e a very long script that takes up to 10 minutes. However, I need the person who calls the script redirected back to the homepage while the script works. In other words, I need the user experience to be something like this:

Is this possible using only PHP? I gather I will need

ignore_user_abort(true); 
set_time_limit(0);

But how do I redirect the user? I can't use javascript because output only gets written to the page at long increments, and I want the redirection to be immediate. Can I use headers? Or will that mess with things?

Alternatively, I could use the cron job approach, but I have zero experience in making a cron job or having it run php code (is that even possible?)

Thanks,
Mala

Update:
Using headers to redirect does not work - the page will not load until the script is done. However, eventually the webserver times out and says "Zero-Sized Reply: The requested URL could not be retrieved" (although the script continues running). I guess my only option is to go with the cron job idea. Ick!

Upvotes: 4

Views: 1833

Answers (4)

Dave Preece
Dave Preece

Reputation: 1

I have a similar situation with processing logins. To keep it short... I get a PDT, IPN and each sends me a logging email. An email is sent to client on IPN VERIFIED to give serial number and password to client. As PDT and IPN I use goto to send me a logging email instead of a bunch of sequential ifs. On reading many answers I studied each to figure what would suit my isssue. I finally used...

<?php
  ignore_user_abort(TRUE); // at very top

As I worked through the progressive checks (no ifs), if they failed I use for example...

  $mcalmsg .= "Check [serialnbr]\r\n";
  if (empty($_POST['serialnbr']))
    {    header('Location: '.$returnurl.'?error=1');
      $mcalmsg .= "Missing [serialnbr]\r\n";
      goto mcal_email; // Last process at end of script        
    }
    else
    {$serialnbr=strtoupper(htmlspecialchars(trim($_POST['serialnbr'])));
     $mcalmsg .= "[serialnbr]=$serialnbr\r\n";
    }

This (so far) is working just as needed. Of course there is more in the script but follows the same concept. Where this says location, there are also 3 information pages that can each be displyed using the same concept.

mcal_email: //last process before ending, always gets here after all else from goto or clearing all checks.
 // compose email and send
?> // end of script

Upvotes: 0

Dan Soap
Dan Soap

Reputation: 10248

The most obvious solution to me would be splitting the redirect and the background calculation in two separate files and let the redirect script execute the 10-minute script:

job.php:

<?php
// do the nasty calculation here

redirect.php:

<?php
// start the script and redirect output of the script to nirvana, so that it
// runs in the background
exec ('php /path/to/your/script/job.php >> /dev/null 2>&1 &'); 

// now the redirect
header ('Location /index.php');

Assumptions for this to work: You should be on a Linux host with either safe_mode disabled or having set the safe_mode_exec_dir appropriately. When you're running under windows, the exec string needs to be adapted, while the rest about safe_mode remains true.

Notice: When you need to pass arguments to the script, use escapeshellarg() before passing it on, see also the PHP manual on exec

Upvotes: 2

Alix Axel
Alix Axel

Reputation: 154603

I've tried several methods and none seems to work, I've even tried to use register_shutdown_function() but that also failed. I guess you're stuck with making a cron job.

I just remembered something (but I haven't tested it), you can try to do something like this:

set_time_limit(0);
ignore_user_abort(true);

ob_start(); // not sure if this is needed

// meta refresh or javascript redirect

ob_flush(); // not sure if this is needed
flush();

// code to process here

exit();

Not sure if it'll work but you can try it out.

Upvotes: 1

Toby Allen
Toby Allen

Reputation: 11211

Why not try the header approach and see what happens? You could also try a call to php header method and see if this does the trick. I would work on trial and error to see what will solve your problem.

Upvotes: -1

Related Questions