Forum Moderators: coopster

Message Too Old, No Replies

Can you dumb down the purpose of flush() and ob flush?

         

csdude55

6:00 am on Nov 22, 2022 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I realize that I've been using flush() for a long time by default, but I'm not entirely sure why. I read this in the docs:

Flushes the system write buffers of PHP and whatever backend PHP is using (CGI, a web server, etc). This attempts to push current output all the way to the browser with a few caveats.

What does that mean in layman's terms?

When is current output not pushed "all the way" to the browser?

Similarly, every time I see flush() in an example I see it paired with ob_flush(). But do I ever need ob_flush() if I don't use ob_start() first?

What's a real world example of when I'd want to use ob_whatever() ?

phranque

8:59 am on Nov 22, 2022 (gmt 0)

WebmasterWorld Administrator 10+ Year Member Top Contributors Of The Month



What does that mean in layman's terms?

PHP will typically buffer the document output.
one reason to do this is so that the HTTP headers can be properly ordered before the HTML document in the response.
When is current output not pushed "all the way" to the browser?

examples of this include compression modules on the server and antivirus tools on the client

robzilla

11:53 am on Nov 22, 2022 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



The ob_ functions are for application-level output buffering. Anywhere in your script you can call ob_start() to place any proceeding output into the output buffer.

Say you wanted to minify the HTML that your PHP script puts out. Place ob_start() to start collecting the output, then later call something like ob_get_clean(), which is a combination of ob_get_contents() and ob_end_clean(), to fetch all the output generated in between. Store that output in a variable like $buffer and then run preg_replace() or whatever to manipulate it, and then echo it out again.

You could also choose not to output anything or everything, but instead to store it in a file or whatever. Or do both for a very simple file-based caching system, for example:
<?php

$cacheFile = 'cache/' . md5($_SERVER['REQUEST_URI']) . '.txt';

if(file_exists($cacheFile)) {

echo $cacheFile;
die();

}

ob_start();

// Generate your output here, e.g. an HTML page

$buffer = ob_get_clean();

file_put_contents($cacheFile, $buffer);

echo $buffer;

?>

When is current output not pushed "all the way" to the browser?

I think the emphasis is on "current". All output that a PHP script generates is generally stored in a buffer, which is automatically flushed and sent to the client once all code processing is completed. Sometimes certain bits of code can take a long time to run and you may want to flush the output buffer earlier so that the client already gets something to work with before the script has been fully processed. You could output something like "Your results are being generated..." early on, and then the rest of the page when it's ready. This requires some collaboration between PHP, your web server, the client, and any other software running in between (e.g. FastCGI), so it can be a little complex to set up, and I don't think it's used much these days. But that's what you'd use flush() for, to flush the system-level output buffer, which operates separately from PHP's output buffer (the ob_ functions).

But do I ever need ob_flush() if I don't use ob_start() first?

Nope.

robzilla

2:21 pm on Nov 22, 2022 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Oops, forgot file_get_contents(). Correction:
if(file_exists($cacheFile)) { 

echo file_get_contents($cacheFile);
die();

}

csdude55

6:03 pm on Nov 22, 2022 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Does this mean that, instead of having flush() at the bottom of the page, I should use it sporadically throughout the document to make the page load progressively? Eg,

echo <<<EOF
<html>
<head>
<!-- header stuff -->
</head>

EOF;

flush();

echo <<<EOF
<body>

<!-- navigation stuff -->

EOF;

flush();

echo <<<EOF
<!-- main stuff -->

EOF;

flush();

echo <<<EOF
<!-- footer stuff -->

EOF;


which, if I'm reading correctly, would make the head load, then the navigation, then the main content, then the footer? And that there wouldn't be any use for flush() after the footer, since at that point everything is pushed?

robzilla

6:10 pm on Nov 22, 2022 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



It's possible if you can get all the software along the way to cooperate (which is a big if these days), but you'd be introducing a lot of overhead so you'll take a performance hit. So I wouldn't use flush() at all, frankly, at least for web pages (might be useful in the CLI, never tried).

Putting flush() at the end of your scripts is indeed pointless because it's default behavior to flush the buffers once script execution has finished.

Sgt_Kickaxe

7:50 pm on Nov 22, 2022 (gmt 0)



You can get creative with it too. It's good to learn.

For example: If you use OB_start and file_put_contents around content and you don't output or echo it you can use a crawler like screaming frog or xenu to crawl your site and generate a quick and dirty static copy of all your pages instantly.

Just be sure to turn off comments, and log out of your application(wordpress etc), before you do or you'll end up with pages that include a broken comment box, and possibly links you should only see when logged in.

If you want to deprecate wordpress because you won't be updating the site again flush is very useful in creating a fully static version.

lucy24

11:07 pm on Nov 22, 2022 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



When is current output not pushed "all the way" to the browser?
When you discover halfway through the process that you won’t be building the page after all. Years ago, I had a clutch of php pages that were made by
-- start a buffer
-- put together the html head
-- look at the parameters and assemble the page accordingly
-- make the bottom of the page
-- send out the whole contents of the buffer
If it turns out in the middle step that the parameters don’t correspond to any valid page, throw out the whole thing and instead send out the 404 page along with a 404 response.
There are of course other ways to do this, but I found this way intuitively simplest.

csdude55

1:16 am on Nov 23, 2022 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



So if I put flush() above the footer stuff that's at the bottom of every page, it should (theoretically) make the page usable slightly faster by forcing the visible part of the page to load before the stuff that's pretty much always going to be below the fold?

Looking at this page on webmasterworld.com for example, if the developer used flush() just after the "Preview" and "Submit" button; eg:

echo <<<EOF
<input class="btn bg-primary" type="submit" name="submit" value="Preview">
&nbsp; &nbsp; &nbsp;
<input class="btn bg-primary" type="submit" value="Submit" name="submit"></form>
</div>
</div>
</div>
</div>

EOF;

flush();

echo <<<EOF
<div class="row">

<!-- yada yada yada -->
EOF;

robzilla

3:11 pm on Nov 23, 2022 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Well, maybe. You'd have to test it to see if it makes a difference these days. But don't expect it to work just by calling flush(), lots of obstacles on the way.

It's a bit of an outdated technique. Google notably once used it for their SERPs. I don't really see any recent talk about it, most is from 10+ years ago.