355

Is ob_start() used for output buffering so that the headers are buffered and not sent to the browser? Am I making sense here? If not then why should we use ob_start()?

0

10 Answers 10

572

Think of ob_start() as saying "Start remembering everything that would normally be outputted, but don't quite do anything with it yet."

For example:

ob_start();
echo("Hello there!"); //would normally get printed to the screen/output to browser
$output = ob_get_contents();
ob_end_clean();

There are two other functions you typically pair it with: ob_get_contents(), which basically gives you whatever has been "saved" to the buffer since it was turned on with ob_start(), and then ob_end_clean() or ob_flush(), which either stops saving things and discards whatever was saved, or stops saving and outputs it all at once, respectively.

6
  • 74
    Great explanation. I would go one step further and replace ob_get_contents() with ob_get_clean() and remove ob_end_clean() since ob_get_clean() essentially performs both functions. Reference: php.net/manual/en/function.ob-get-clean.php (PHP 4 >= 4.3.0, PHP 5) Commented May 20, 2015 at 16:49
  • 1
    I assume output buffering has to be enabled in the .ini file order to call ob_start(); Is this correct? What happens if it isn't enabled? Commented Aug 14, 2015 at 3:48
  • 7
    @Riley Dutton You are not telling that why does the ob_start() is used Commented Oct 14, 2015 at 4:32
  • Had the same issue, after fixing my code with ob_end_clean it works like a charm! Thanks @Riley Dutton
    – Martins
    Commented Jan 14, 2016 at 8:02
  • @Kevin Wheeler If output buffering was not enabled in PHP.ini or .htaccess (which sometime but not always works), and no previous ob_start was done, then ob_get_contents will return an empty string. The output may eventually be flushed, where it would appear as the output of the web page. Commented Apr 25, 2021 at 19:58
200

I use this so I can break out of PHP with a lot of HTML but not render it. It saves me from storing it as a string which disables IDE color-coding.

<?php
ob_start();
?>
<div>
    <span>text</span>
    <a href="#">link</a>
</div>
<?php
$content = ob_get_clean();
?>

Instead of:

<?php
$content = '<div>
    <span>text</span>
    <a href="#">link</a>
</div>';
?>
5
  • 1
    Can this be used as a way to have multiple html pages within one PHP and call them via GET?
    – joshkrz
    Commented Dec 28, 2012 at 21:56
  • 1
    I suppose so but it doesn't sound like a good idea. It would be better to load them from separate templates.
    – JD Isaacks
    Commented Jan 20, 2013 at 7:58
  • 1
    Note that this technique uses ob_get_clean(), not ob_end_clean() Commented Nov 25, 2013 at 19:47
  • 14
    Never thought of this, that's an incredibly IDE-friendly way to develop! Plus, it removes my need to have Javascript or HTML as a string in my PHP, constantly escaping \" etc, which is annoying
    – J-Dizzle
    Commented Nov 5, 2014 at 17:14
  • 1
    Your visual gives a clear picture on the benefits of using ob_start.
    – klewis
    Commented Apr 3, 2019 at 3:42
101

The accepted answer here describes what ob_start() does - not why it is used (which was the question asked).

As stated elsewhere ob_start() creates a buffer which output is written to.

But nobody has mentioned that it is possible to stack multiple buffers within PHP. See ob_get_level().

As to the why....

  1. Sending HTML to the browser in larger chunks gives a performance benefit from a reduced network overhead.

  2. Passing the data out of PHP in larger chunks gives a performance and capacity benefit by reducing the number of context switches required

  3. Passing larger chunks of data to mod_gzip/mod_deflate gives a performance benefit in that the compression can be more efficient.

  4. buffering the output means that you can still manipulate the HTTP headers later in the code

  5. explicitly flushing the buffer after outputting the [head]....[/head] can allow the browser to begin marshaling other resources for the page before HTML stream completes.

  6. Capturing the output in a buffer means that it can redirected to other functions such as email, or copied to a file as a cached representation of the content

1
  • Important note: it is not necessary to call ob_start() the first time on a page if you have output buffering enabled in PHP.ini, like this: output_buffering = 200000. In some cases, but not all, such enabling can be done in an .htaccess file, like this: php_value output_buffering 200000. Commented Apr 25, 2021 at 19:52
35

You have it backwards. ob_start does not buffer the headers, it buffers the content. Using ob_start allows you to keep the content in a server-side buffer until you are ready to display it.

This is commonly used to so that pages can send headers 'after' they've 'sent' some content already (ie, deciding to redirect half way through rendering a page).

1
  • 3
    +1 I too was confused as to the actual usage of the function. Your answer regarding its use during "redirection" reminded me of all the times that i have had the error "Headers already sent". Thanks
    – pat
    Commented Feb 2, 2014 at 19:40
16

I prefer:

ob_start();
echo("Hello there!");
$output = ob_get_clean(); //Get current buffer contents and delete current output buffer
1
  • This is the right way to get echoed contents, or contents outside of PHP tags. If you need to get further output, you will need a final ob_start call. Commented Apr 25, 2021 at 19:55
15

this is to further clarify JD Isaaks answer ...

The problem you run into often is that you are using php to output html from many different php sources, and those sources are often, for whatever reason, outputting via different ways.

Sometimes you have literal html content that you want to directly output to the browser; other times the output is being dynamically created (server-side).

The dynamic content is always(?) going to be a string. Now you have to combine this stringified dynamic html with any literal, direct-to-display html ... into one meaningful html node structure.

This usually forces the developer to wrap all that direct-to-display content into a string (as JD Isaak was discussing) so that it can be properly delivered/inserted in conjunction with the dynamic html ... even though you don't really want it wrapped.

But by using ob_## methods you can avoid that string-wrapping mess. The literal content is, instead, output to the buffer. Then in one easy step the entire contents of the buffer (all your literal html), is concatenated into your dynamic-html string.

(My example shows literal html being output to the buffer, which is then added to a html-string ... look also at JD Isaaks example to see string-wrapping-of-html).

<?php // parent.php

//---------------------------------
$lvs_html  = "" ;

$lvs_html .= "<div>html</div>" ;
$lvs_html .= gf_component_assembler__without_ob( ) ;
$lvs_html .= "<div>more html</div>" ;

$lvs_html .= "----<br/>" ;

$lvs_html .= "<div>html</div>" ;
$lvs_html .= gf_component_assembler__with_ob( ) ;
$lvs_html .= "<div>more html</div>" ;

echo $lvs_html ;    
//    02 - component contents
//    html
//    01 - component header
//    03 - component footer
//    more html
//    ----
//    html
//    01 - component header
//    02 - component contents
//    03 - component footer
//    more html 

//---------------------------------
function gf_component_assembler__without_ob( ) 
  { 
    $lvs_html  = "<div>01 - component header</div>" ; // <table ><tr>" ;
    include( "component_contents.php" ) ;
    $lvs_html .= "<div>03 - component footer</div>" ; // </tr></table>" ;

    return $lvs_html ;
  } ;

//---------------------------------
function gf_component_assembler__with_ob( ) 
  { 
    $lvs_html  = "<div>01 - component header</div>" ; // <table ><tr>" ;

        ob_start();
        include( "component_contents.php" ) ;
    $lvs_html .= ob_get_clean();

    $lvs_html .= "<div>03 - component footer</div>" ; // </tr></table>" ;

    return $lvs_html ;
  } ;

//---------------------------------
?>

<!-- component_contents.php -->
  <div>
    02 - component contents
  </div>
7

Following things are not mentioned in the existing answers : Buffer size configuration HTTP Header and Nesting.

Buffer size configuration for ob_start :

ob_start(null, 4096); // Once the buffer size exceeds 4096 bytes, PHP automatically executes flush, ie. the buffer is emptied and sent out.

The above code improve server performance as PHP will send bigger chunks of data, for example, 4KB (wihout ob_start call, php will send each echo to the browser).

If you start buffering without the chunk size (ie. a simple ob_start()), then the page will be sent once at the end of the script.

Output buffering does not affect the HTTP headers, they are processed in different way. However, due to buffering you can send the headers even after the output was sent, because it is still in the buffer.

ob_start();  // turns on output buffering
$foo->bar();  // all output goes only to buffer
ob_clean();  // delete the contents of the buffer, but remains buffering active
$foo->render(); // output goes to buffer
ob_flush(); // send buffer output
$none = ob_get_contents();  // buffer content is now an empty string
ob_end_clean();  // turn off output buffering

Nicely explained here : https://phpfashion.com/everything-about-output-buffering-in-php

6

This function isn't just for headers. You can do a lot of interesting stuff with this. Example: You could split your page into sections and use it like this:

$someTemplate->selectSection('header');
echo 'This is the header.';

$someTemplate->selectSection('content');
echo 'This is some content.';

You can capture the output that is generated here and add it at two totally different places in your layout.

1
  • This kind of looks like what I'm looking for. I need to render stuff to 'sections' (think of JS and CSS files), but I need to be able to call them within the template (which gets loaded later than the header)... So if I call "$this->addcss('specificCSStoThisView');" I want it to render between the <head> tags. I can't seem to google this, however. Could you maybe point me in the right direction? Thank you!
    – NoobishPro
    Commented Dec 5, 2015 at 1:01
0

No, you are wrong, but the direction fits ;)

The Output-Buffering buffers the output of a script. Thats (in short) everthing after echo or print. The thing with the headers is, that they only can get sent, if they are not already sent. But HTTP says, that headers are the very first of the transmission. So if you output something for the first time (in a request) the headers are sent and you can not set any other headers.

-3

Output Buffering ob_start(), is a process that tells PHP to hold the output data in a variable as a string before sending it to the client. In general, PHP sends the data to the browser in pieces. But if we use the output buffering feature, it sends the output data altogether to the browser in one piece when the PHP script ends instead of sending data in various pieces.

The following code helps you to understand it clearly.

<?php
ob_start(); // output buffering is turned on
echo "Inside of output buffering section.";
$output = ob_get_clean(); // stopped the output store the output in the output variable

echo "Outside of output buffering section.<br>";
echo $output;
?>

/*
The output will be like this :

Inside of output buffering section.
Outside of output buffering section.

*/

ob_get_clean() silently discards the buffer contents.

Also, there is another function ob_get_contents() that grabs all of the data gathered since we called ob_start.

Advantages of output buffering

  1. Enabling output buffering decreases the download time it takes and renders the HTML in the browser. At the same time, it decreases the PHP script execution time.
  2. On the other hand sometimes we get this warning "Warning: Cannot modify header information - headers already sent by (output)" when we set cookies, we can solve that issue using this output buffering.

You can see more about it that is explained here.

3
  • 1
    Why are you just copy/pasting the exacts words from the tutorial? Can't you use your own words? I'm not even sure you are allowed to just copy/paste tutorials from tutorialspoint.com as code posted on SO is licensed under another license than the intended license on tutorialspoint. See here and see the FAQ on tutorialspoint - "Can we reuse/publish the content available on tutorialspoint.com?"
    – DarkBee
    Commented Jul 13, 2023 at 8:17
  • 1
    Misleading. $output = ob_end_clean(); -- this does not returns output. Commented Jul 17, 2023 at 5:15
  • @AlekseyKuznetsov Thank you for letting me know. I have changed the misspelling of the function I used. Now it is correct. Commented Jul 17, 2023 at 14:03

Not the answer you're looking for? Browse other questions tagged or ask your own question.