views:

390

answers:

5

I first configure my script to run even after the HTTP request is over

 ignore_user_abort(true);

then flush out some text.

 echo "Thats all folks!";
 flush();

Now how can I trick the browser into thinking the HTTP request is over? so I can continue doing my own work without the browser showing "page loading".

 header(??) // something like this?
+4  A: 

Headers won't work (they're headers, so they come first)

I don't know of any way to close the http connection without terminating the script, though I suppose there's some obscure way of doing it.

Telling us what you want to do after the request is done would help us give better suggestions.

But generally, I'd be thinking about one of the following:

1) Execute some simple command-line script (using exec()) that looks like:

#!/bin/sh
php myscript.php <arg1> <arg2> .. <argN> &

Then kick that off from your http-bound script like:

<?PHP
exec('/path/to/my/script.sh');
?>

Or:

2) Write another program (possibly a continuously-running daemon, or just some script that is cronned ever so often), and figure out how your in-request code can pass it instructions. You could have a database table that queues work, or try to make it work with a flat file of some sort. You could also have your web-based script call some command-line command that causes your out-of-request script to queue some work.

At the end of the day, you don't want your script to keep executing after the http request. Assuming you're using mod_php, that means you'll be tying up an apache process until the script terminates.

timdev
+1 Agreed. Continuing execution after a web request would be a poor design choice, and would incur unnecessary memory overhead on the server.
Fragsworth
Big time agreed with Tim. The whole point of the question is that you want to save a chunk of work for later, and not make the user wait. Well, you're just tying up httpd resources that might block other users. Let httpd handle web clients and pass off the other work to another component - daemon (+1 for real time), scheduled job (+1 for batching and queueing erata processing that can REALLY wait), or whatever.
Sam Bisbee
+2  A: 

Theoretically, if HTTP 1.1 keep-alive is enabled and the client receives the amount of characters it expects from the server, it should treat it as the end of the response and go ahead and render the page (while keeping the connection still open.) Try sending these headers (if you can't enable them another way):

Connection: keep-alive
Content-Length: n

Where n is the amount of characters that you've sent in the response body (output buffering can help you count that.) I'm sorry that I don't have the time to test this out myself. I'm just throwing in the suggestion in case it works.

Ates Goral
Still a bad idea, as if the post-request processing takes more than a few ms (in which case why the hurry to end the connection), you're better off releasing the web server process to handle new requests, and have some back-end process (not tied to the httpd) take over.
timdev
I do agree that this is probably a bad idea. It's just an attempt to satisfy the OP's requirement.
Ates Goral
+1  A: 

Maybe this particular comment on php.net manual page will help: http://www.php.net/manual/en/features.connection-handling.php#71172

Lukman
This is where the code in the accepted answer came from.
GZipp
+2  A: 

The best way to accomplish this is using output buffering. PHP sends the headers when it's good and ready, but if you wrap your output to the browser with ob_* you can control the headers every step of the way.

You can hold a rendered page in the buffer if you want and send headers till the sun comes up in china. This practice is why you may see a lot of opening <?php tags, but no closing tags nowadays. It keeps the script from sending any headers prematurely since there might some includes to consider.

Jesse Kochis
+1  A: 

Here's how to do it. You tell the browser to read in the first N characters of output and then close the connection, while your script keeps running until it's done.

<?php
ob_end_clean();
header("Connection: close");
ignore_user_abort(); // optional
ob_start();
echo ('Text the user will see');
$size = ob_get_length();
header("Content-Length: $size");
ob_end_flush();     // Will not work
flush();            // Unless both are called !

// At this point, the browser has closed connection to the web server

// Do processing here
echo('Text user will never see');
?>
Milan Babuškov
+1 Brilliant solution! Thanks for the wisdom that all the king's horsemen couldn't figure out.
Jenko
Really nice hack by Milan. But I am have to wonder what it is you're doing that requires chewing up a web server process after the web request is over (from the client's perspective).I certainly hope this abomination is not expected to scale very much!
timdev
Identical (to the letter) to the code in the php manual page linked to in Lukman's answer, which was posted two days earlier.
GZipp