When we say that a function's result is sent to output buffer, it means that the result is not visible until echoed. And for functions that output directly, we use ob_start to direct the result to the output buffer (before it hits the browser as plain html) so that we may manipulate it, and then if desired, echo it.
The result of the function readfile() is directly visible, which is the contents of a certain text file, for example. then my question is:
Why it is mentioned in php documentation that readfile() sends the contents to the output buffer ?! (while in fact it is displayed directly).
Am I missing something?
When we say that a function's result is sent to output buffer, it means that the result is not visible until echoed. No it doesn't mean that!
Because it is sent to the output buffer, which (unless you've explicitly executed an ob_start() to buffer the output before sending it to the browser) is sent directly to the browser (or whatever).
All output is sent to the output buffer, but unless you've set the buffer to hold output before sending it, it gets sent.
EDIT
Of course, a webserver may be configured to cache output until a certain volume of data has been sent, but that isn't the same as PHP output buffering
Well, when the readfile() is executed, the output goes directly to stdout.
it is useful to know this behavior when php is used as a bash script:
#!/usr/bin/php
<?php
readfile("cool.txt");
// Output cool.txt whole content
It behave differently to file_get_contents from this view.
#!/usr/bin/php
<?php
file_get_contents("js.txt");
// No output!
$cool = file_get_contents("js.txt");
echo $cool;
// Output cool.txt
Related
I know that ob_start turns on output buffering, but I don't fully understand what it means. To me it means that it just stops outputting the script data.
Is this true? How does the browser output data in this case, do I have to use ob_end_flush() to turn it off in the end?
Since ob_gzhandler compresses web pages, how do browsers handle these pages?
I have seen ob_start("gzhandler") in code, since ob_gzhandler compresses web pages, what does ob_start("gzhandler") mean and how does it apply to both functions?
All help appreciated!
Output buffering means that instead of writing your output directly to the stdout stream, it is instead written to a buffer.
Then when the script finishes (or when you call ob_end_flush()), the contents of that buffer are written to stdout.
Using ob_gzhandler transforms the contents of the buffer before writing it to stdout, such that it is gzip compressed. (Browsers which support gzip compression reverse this on the opposite end, decompressing the content.)
Ok, let me explain it like this,
It is only one of the uses of the buffer system but I think it's kinda cool.
first I want you to look to this animation.
Operating System Start
When you have a php script that has a level based structure like this, for example you may write:
Connection established to database server..
Database selected : my_database
Data query started
Data query ended (found:200 rows)
...
etc. but if you don't use output buffering and flushing, you will see these lines when all of your script execution ends. But, when the thought is "I want to see what my script is doing when!", you first need to..
Sorry you first need to set implicit_flush to "on" at your php.ini file and restart your apache server to see all of this.
second, you need to open the output buffering (shorthand "ob") by "ob_start();", and then,
place anywhere on your code "echo" statements and after that "ob_flush();" commands to see your script running on realtime.
Later, it is also used for file based static content buffering like this:
place ob_start() at the start of your page (or the start of content you want to capture)
place ob_end_flush() at the end of your page (or the end of content you want to capture);
then $my_var = ob_get_contents(); to get all the HTML output that server creates and sends to the client into my_var variable and then use it as you want. Mostly it's saved to a file and by checking the file's last modification date, it's used as a static buffering.
I hope I could light some bulbs on your mind.
Can anyone explain why I am receiving the following error?
In the code, if the echo $gz; is commented out I receive no error (but also no output!), if it isn't I get (from Firefox),
Content Encoding Error
The page you
are trying to view cannot be shown
because it uses an invalid or
unsupported form of compression.
Thanks for your help, here's the code:
ob_start('ob_gzhandler') OR ob_start();
echo 'eh?';
$gz = ob_get_clean();
echo $gz;
The output of your application should only contain one output encoding. If you have multiple chunks that are encoded differently, then the browser will get a result that it is impossible to work with. Hence the encoding error.
Kohana itself makes already use of the output buffer. If you want to combine that with your ob_gzhandler output buffer, you need to start your buffer before kohana initialized it's own. That's because output buffer are stackable. When kohana has finished it's output buffering, yours will apply:
ob_start('ob_gzhandler'); # your buffer:
ob_starts and ends by kohana
So whenever kohana has done some output, these chunks will get passed on into your output callback (ob_gzhandler()) and will be gz-encoded.
The browser should then only get gz-encoded data as it was the output buffer at the topmost level.
Using ob_gzhandler and manually echo'ing the buffer
If you make use of ob_start('ob_gzhandler') to let PHP deal with the compression and you then echo ob_get_clean(), you will create an unreliable output. That's related to how the compression togther with output buffering works:
PHP will buffer chunks of output. That means, PHP starts to compress the output but keeps some bytes to continue compressing. So ob_get_clean() returns the so-far compressed part of the buffer. Often that result is not complete.
To deal with that, flush the buffer first:
ob_start('ob_gzhandler') OR ob_start();
echo 'eh?';
ob_flush();
$gz = ob_get_clean();
echo $gz;
And ensure you don't have any more output after that.
If you would have PHP reached the end of your script, it would have taken care of that: Flushing and outputting.
Now you need to manually call ob_flush() to explicitly make PHP push the buffer through the callbacks.
Inspecting HTTP Compression Problems with Curl
As firefox will return an error, another tool to inspect what's causing the encoding error is needed. You can use curl to track what's going on:
curl --compress -i URL
Will request the URL with compression enabled while displaying all response headers and the body unencoded. This is necessary as PHP transparently enables / disables compression of the ob_gzhandler callback based on request headers.
A response also shows that PHP will set the needed response headers as well. So no need to specify them manually. That would be even dangerously, because only by calling ob_start('ob_gzhandler') you can not say if compression is enabled or not.
In case the compression is broken, curl will give an error description but would not display the body.
Following is such a curl error message provoked with an incompletely generated output by a faulty php script:
HTTP/1.1 200 OK
X-Powered-By: PHP/5.3.6
Content-Encoding: gzip
...
curl: (23) Error while processing content unencoding: invalid code lengths set
By adding the --raw switch, you can even peak into the raw response body:
curl --compress --raw -i URL
That can give an impression what's going wrong, like uncompressed parts within the body.
This is what phpharo does:
/** output buffring */
if (isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false)
{
ob_start('ob_gzhandler'); ob_start();
}
else
{
ob_start();
}
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()?
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.
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>
link
</div>
<?php
$content = ob_get_clean();
?>
Instead of:
<?php
$content = '<div>
<span>text</span>
link
</div>';
?>
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....
Sending HTML to the browser in larger chunks gives a performance benefit from a reduced network overhead.
Passing the data out of PHP in larger chunks gives a performance and capacity benefit by reducing the number of context switches required
Passing larger chunks of data to mod_gzip/mod_deflate gives a performance benefit in that the compression can be more efficient.
buffering the output means that you can still manipulate the HTTP headers later in the code
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.
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
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).
I prefer:
ob_start();
echo("Hello there!");
$output = ob_get_clean(); //Get current buffer contents and delete current output buffer
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>
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
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.
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.
I am having a php file which executes some code to generate a html file.Its like I m having a form from which some data will be posted to x.php file, which gives a output(a webpage). I want to save that output in a html file.What the most efficient way of doing this.?
EDIT
I want to save it on sever side. Actually the thing is i want to create pdf file for that.. I wrote everything else.Now the thing is i want to save the output in a html page.So that i can convert it into pdf file..
Try something like this:
// Start output buffering
ob_start();
// run code in x.php file
// ...
// saving captured output to file
file_put_contents('filename.htm', ob_get_contents());
// end buffering and displaying page
ob_end_flush();
If you cannot use the ob_* functions, you can also write the form to a variable and then save that variable.
Look at ob functions (see http://php.net/manual/en/function.ob-start.php) that allows you to capture every output (echo, print, etc...) from the page.
using ob_* functions such as ob_get_contents(), a php script can catch it's output.
probably with ob_start and output_callback see http://php.net/manual/en/function.ob-start.php
I have a php that makes some maintenance operations in my web and I need that the last operation it'll do is to save into a file the content of the screen. I mean, self content.
If the screen shows: "OP1 - OK ..." it has to save into a file this: "OP1 - OK ...".
Saving all the results of my operations into a variable will very hard for me. That's why I need to get the content of the self screen.
Is there any way to do this?
I think you can use an output buffer.
The following is from ob_start's php manual page:
This function will turn output buffering on. While output buffering is active no output is sent from the script (other than headers), instead the output is stored in an internal buffer.
The contents of this internal buffer may be copied into a string variable using ob_get_contents(). To output what is stored in the internal buffer, use ob_end_flush(). Alternatively, ob_end_clean() will silently discard the buffer contents.