0

I thought flush(); would work, at least from what Google/Stackoverflow tell me, but on my Windows WAMP (Windows, Apache, MySQL, PHP) system it doesn't work.

Is there some PHP setting I have to set to make flush() work?

Here's my code:

<?php
echo "Fun";

flush();

sleep(5);

echo "<br>Mo";
?>

The code just outputs all together when the script is done executing (after 5 seconds).. I don't want this, I want 'Fun' to show up right away, and then after 5 seconds 'Mo'.

I've tried other combinations of flush like ob_end_flush(); or ob_implicit_flush(true); but nothing is working. Any ideas?

Luca Matteis
  • 29,161
  • 19
  • 114
  • 169
  • did you check php.ini setting of implicit_flush? – bcosca Aug 14 '10 at 11:18
  • @stillstanding, Yes I've turned that On and also tried setting `ini_set('implicit_flush', true);` ... still not working... i'm starting to think it has something to do with a bug on windows. – Luca Matteis Aug 14 '10 at 11:22
  • zlib.output_compression will also activate buffering if it's on. – bcosca Aug 14 '10 at 11:31

6 Answers6

7

So that's what I found out:

Flush would not work under Apache's mod_gzip or Nginx's gzip because, logically, it is gzipping the content, and to do that it must buffer content to gzip it. Any sort of web server gzipping would affect this. In short, at the server side, we need to disable gzip and decrease the fastcgi buffer size. So:

  • In php.ini:

    . output_buffering = Off

    . zlib.output_compression = Off

  • In nginx.conf:

    . gzip off;

    . proxy_buffering off;

Also have this lines at hand, specially if you don't have acces to php.ini:

  • @ini_set('zlib.output_compression',0);

  • @ini_set('implicit_flush',1);

  • @ob_end_clean();

  • set_time_limit(0);

Last, if you have it, coment the code bellow:

  • ob_start('ob_gzhandler');

  • ob_flush();

PHP test code:

ob_implicit_flush(1);

for($i=0; $i<10; $i++){
    echo $i;

    //this is for the buffer achieve the minimum size in order to flush data
    echo str_repeat(' ',1024*64);

    sleep(1);
}
Roger
  • 8,286
  • 17
  • 59
  • 77
5

The script works fine from CLI, displaying "Fun", waiting 5 secs before displaying "<br>Mo".

For a browser the results might be a bit different because:

  1. The browser wont start rendering right away. Getting 3 bytes of data for HTML document isn't enough to do anything, so it'll most likely wait for a few more.
  2. Implicit IO buffering on the lib level will most likely be active until a newline is received.

To work around 1) use text/plain content type for your test; 2) needs newlines, so do an echo "Fun\n"; and echo "<br>Mo\n"; Of course you wont be using text/plain for real HTML data.

jmz
  • 5,399
  • 27
  • 29
  • Yeah, I like your answer. Also can be client-side. :-) – Savageman Aug 14 '10 at 11:41
  • You're right... I've been using Chrome all this time and it wasn't working. Trying my initial example (even without newlines and text/plan output) on Firefox worked great... I wonder if there's a way to make this work cross-browser... +1 but you might want to take out the \n and text/plain stuff. – Luca Matteis Aug 14 '10 at 11:56
3

If you're using CGI/FastCGI, forget it! These don't implement flush. The Webserver might have it's own buffer.

You can disable all output buffering in PHP with following command:

ob_implicit_flush();
Vincent
  • 2,342
  • 1
  • 17
  • 22
1

If the problem persists, although you explicitly set

implicit_flush = yes 

in your php.ini, you might also want to set

output_buffering = off

which did the trick in my case (after pulling my hair for 4+hrs)

Philipp
  • 45
  • 1
  • 4
0

Check your php.ini for output_buffering.

tamasd
  • 5,747
  • 3
  • 25
  • 31
0

Maybe the problem is Apache here, which also may have buffers...

Savageman
  • 9,257
  • 6
  • 40
  • 50