views:

47

answers:

2

I'm trying to run a loop every second for 25 seconds basically.

for($i = 0; $i <= 25; $i += 1){ 
    echo $i;
    sleep(1)
}

The thing is it doesn't output until it's fully done, so after the loop continues 25 times. Is there a way to do this so it will output before each sleep? and not wait until the full loop is complete?

Thanks!

+2  A: 

Call flush will force PHP to push all of the output buffer to the client before proceeding.

for($i = 0; $i <= 25; $i += 1){ 
    echo $i;
    flush();
    sleep(1);
}

EDIT:

After testing this on my lighttpd server I noticed that it buffered my outputs in blocks of 4096 characters, and I assume other browser might have similar buffering schemes. Also GZIP can prevent flush completely. Unfortunately there is no way to test that it's working due to the nature of HTTP.

Also another issue with this strategy is that it leaves that PHP proc blocked to other requests. This can cause requests to pile up.

Kendall Hopkins
Hmm.. Didn't seem to do the trick.. also tried w/ ob_start(), ob_flush() and flush()
Dave
Usually the combo of `ob_end_flush()` (skip the `ob_start()`) and `flush()` does it. Do you have a proxy server between you and the server running PHP?
Adam Backstrom
Worked for me running via command line, but not the browser...after I put a semicolon after the sleep(1)
Aaron W.
No, no proxy...
Dave
@Dave try using curl via commandline, it's possible your browser is buffering it. If that's the case, you can't fix it w/o switching browsers.
Kendall Hopkins
+1  A: 

What you're trying to achieve is incremental output to the browser from PHP.

Whether this is achievable can depend on your server and how you're invoking PHP.

PHP under FastCGI

You're most likely to run into a problem when PHP is running under FastCGI (ie mod_fcgid). This Apache module is really intended for processes which complete very quickly and don't need to stay alive. Output is all redirected to a memory buffer and only sent to the client in one go, or when the buffer runs out. On top of that, it usually enforces a maximum process lifetime so if your script runs for too long it'll be killed. PHP functions like set_time_limit() and flush() won't overcome this. You could tweak the buffer so it's much smaller, but then you lose a lot of the benefit of FastCGI. You may want to consider moving to a client-side model where you are using Javascript and perhaps AJAX calls to do what you want to do, and if you need background processing, run a daemon or cron job on the server.

PHP under mod_php

If you're using mod_php, you can write incrementally out to the browser. Use the flush() command to ensure that the PHP module will flush it instantly. If you don't have output buffering, or some Apache module such as mod_gzip, then it should go out instantly to the user's browser. What's more, you can keep your PHP script running as long as you like (with set_time_limit() in PHP), under the default configurations, though of course it will consume some memory.

You may run into trouble with some browsers which don't start rendering the page until a certain amount of a page is downloaded. Some versions of IE may wait for 1KB. I've found that Chrome can wait for more. A lot of people get around this by adding padding, such as a long comment 1 or 2 KB long at the top of the document.

thomasrutter