Forum Topic: Php: Output Buffering

(1,096 views • 4 replies)

This topic is 1 page long.

<< < > >>
None

NinoGrounds

Reply To Post Reply & Quote

Posted at: 8/3/06 01:45 PM

NinoGrounds EVIL LEVEL 17

Sign-Up: 11/28/05

Posts: 3,756

[PHP: Main]

PHP: Output Buffering (OB)

Prologue
What can I use OB for?
OB is generally used for controling data which is sent to the Browser.
With that power, we can freely use specific functions at any place. This is, as you may guess, not possible without OB.
For instance, header() or setcookie().
Those should be placed before anything is sent to the browser, which really includes everything, even a whitespace or a tab.
And just don't think that HTML tags aren't considered too. Putting tag body is considered as <p>Hello!</p>!

Those, if used after anything is sent to the browser, will issue, and will generate this (in case you used header()):

Warning: Cannot modify header information - headers already sent by (output started at <filename>:<line>) in <filename> on line <line>

Note that this is a Warning, not a fatal error.
The difference is:
- warning will just output a error message
- fatal error will output a error and stop the executing of a script

(note that either warning or fatal error isn't parse error, which is done before the document executed)

Alt Way
If you don't want to learn OB, here's a simple method of leting headers to go even after the data is set.
This method is, of course, deprecated, meaning it won't work everywhere, because it contacts with php.ini, which is not enabled on every host.

<?
if (ini_get('output_buffering') == NULL || ini_get('output_buffering') == 'Off') {
$amount = 4096;
ini_set('output_buffering', $amount);
}
?>

If, somehow, that scripts affects your php.ini, but your script still doesn't work, you can try increasing the variable $amount.
Or, even if you put $amount to some huge number and it still doesn't help, instead of numbers, put a string 'On'.
That will, however, insignifiscantly slow down your script.
Also do note that this won't actually re-write a part of php.ini; this is done at runtime.

If you want to explore php.ini further, use this:

<?
$php = ini_get_all();

foreach ($php as $titles => $values) {
foreach ($values as $get) {
$basic = "# $titles =&gt; $get <br /> \n";
$ob = str_replace("output_buffering", "======&gt; output_buffering", $basic);
echo $ob;
}
}
?>

Easiest Example

<?
// output 'Whassup dude!?';
echo "Whassup dude!?";
// redirect
header ("location: i.php");
?>

Issues - data already transmitted to browser.

So the right thing would be that script in vica-versa order.
That is, most likely, impossible.
So that's why we must use OB now.

Summary
You start OB with ob_start().
You turn off OB with many functions. We'll use ob_end_flush() now.

<?
// turn on OB
ob_start();
// output a message
echo "Whassup dude!?";
// redirect
header ("location: i.php");
// turn off OB
ob_end_flush();
?>

And that's it!
It would work.
You can quit this tutorial right now - all you need to do to avoid header() and setcookie() warnings is to put ob_start() before everything is sent to browser and ob_end_flush() after everything is sent to the browser.

Additional Material - Dealing with Output
In this chapter, you will learn some more advanced OB functions, ob_get_clean.

ob_get_clean is a combination of calling ob_get_contents and ob_end_clean.
It works so (be sure that there is ob_start() before!):

1) gets the current data (the data is everything what is outputed after calling ob_start()). so be sure to format your ob_get_clean function thus:

$[var name] = ob_get_clean();

And that will store the current buffer into that variable.

2) deletes the current buffer. of course, a backup of it is stored in a variable you've specified.

Example

<?
// send some data, but firstly, turn on OB
ob_start();
echo "Hello, we are the protagonists.";
$data = ob_get_clean();
?>

Up to this point, nothing is outputed to the browser.

<?
// ... continuing from the previous script
echo $data;
?>

Responds with outputing "Hello, we are the protagonists." to the browser.

Implicit Flush
ob_implicit_flush() is yet another OB function which doesn't require turning OB on with ob_start().
So what does ob_implicit_flush() do?

ob_implicit_flush() is generally used when working with cross-domain scripts.
Like, sockets (fsockopen()) or transmitting data from one server to another.

This function will send data to the browser immediatly, when the server accepts it.
This is helpful only for networking jobs, as mentioned before.

Turning ob_implicit_flush() on will, of course, have its bad sides.
Firstly, it will signifiscantly slow down your pages.

On the other hand, you can always have implicit_flush on.
To do so, you must, as above, change php.ini at runtime.
Thus:

<?
ini_set('implicit_flush', 'On');
?>

Function Overview
ob_start() - turns on OB. to start using OB, you must put that. be sure to put it before anything is sent to the browser, to avoid conflicts. you can have any number of ob_start()'s in your document. however, again, to avoid conflicts, be sure to have the same number of ending OB's. like, ih you have 10 ob_start()'s in your document, you must have 10 ob_end_flush()'es (or ob_end_clean()'es, whatever). calling clearstatcache() beetwen ob_start() and functions which ends OB makes no difference.

ob_end_flush() - turns off the OB and sends everything what should be outputed (like echo()'ed strings) to the browser.

ob_end_clean() - turns off the OB, but, unlike the ob_end_flush(), the buffered data is not sent to the browser.
briefly - a internal buffer storage is simply cleaned.

ob_get_flush() - works like a doubler. everything which is already in the buffer will be outputed.

Example:
<?
ob_start();
echo "Flush me twice!";
echo ob_get_flush();
ob_end_flush();
?>

As you probably expected, this outputes:

Flush me twice!Flush me twice!

ob_get_length() - a simple function. returns the length of the current buffer, in bytes.

Thanks for Reading

Nino

if you have any questions feel free to post them, or if you need help with your script (related to OB) feel free to PM me!


None

DFox

Reply To Post Reply & Quote

Posted at: 8/3/06 02:00 PM

DFox LIGHT LEVEL 30

Sign-Up: 08/09/03

Posts: 9,463

Cool. Nice tutorial.

We recommend output buffering frequently on this forum, and now we'll have a nice tutorial to link to.


None

NinoGrounds

Reply To Post Reply & Quote

Posted at: 8/3/06 02:06 PM

NinoGrounds EVIL LEVEL 17

Sign-Up: 11/28/05

Posts: 3,756

At 8/3/06 02:00 PM, GamesCool wrote: We recommend output buffering frequently on this forum, and now we'll have a nice tutorial to link to.

Yes, that's why I actually made it.
Noobs often get the warnings because of the headers, so, this will help them.


None

authorblues

Reply To Post Reply & Quote

Posted at: 8/3/06 02:37 PM

authorblues FAB LEVEL 12

Sign-Up: 06/21/05

Posts: 6,362

i want to append my 2 cents to this:

using output buffering to give accurate information to the browser
when unspecified, the header value "content-length" is an approximate, which becomes even more inaccurate when dynamic pages, like php, are loaded, since all the browser has to go on is the server's "opinion" of its size. but how to make this better?

JUST before you flush your output buffer, consider sending one last header out:
header('Content-Length: '.ob_get_length());

problem solved :D

GENERATION 1-i: The first time you see this, copy it into your sig on any forum. Square it, and then add i to the generation.

BBS Signature

None

NinoGrounds

Reply To Post Reply & Quote

Posted at: 8/3/06 03:04 PM

NinoGrounds EVIL LEVEL 17

Sign-Up: 11/28/05

Posts: 3,756

Alright.

Extending's good.


All times are Eastern Standard Time (GMT -5) | Current Time: 09:27 PM

<< Back

This topic is 1 page long.

<< < > >>
You need a Grounds Gold Account to post on the NG BBS! If you don't have one, click here to sign up now! It's fast, free, and easy — and opens up tons of great NG features!