PHP ob_start() question - php

Am I allowed to have two or more ob_start(); in my php files if so what is the proper way to end one ob_start(); and start another?

From the manual:
Output buffers are stackable, that is,
you may call ob_start() while another
ob_start() is active. Just make sure
that you call ob_end_flush() the
appropriate number of times. If
multiple output callback functions are
active, output is being filtered
sequentially through each of them in
nesting order.
In addition to stacking (nesting), you can have separate blocks in sequence.
<?
ob_start();
echo "Foo";
ob_end_flush(); // outputs buffer contents and turns off output buffering
ob_start();
echo "Bar";
ob_end_flush();
?>

You are allowed to do more than one ob_start() on a page. You end ob_start() with ob_end_clean().
ob_start();
$postOutput = preg_replace('/<img[^>]+./','', ob_get_contents());
ob_end_clean();
echo $postOutput;

Related

Ob_flush without discarding buffer

I have a PHP script that takes a few minutes to finish processing. While the page is still loading, I want to show part of the PHP output as it becomes available, which can be done using ob_start() and ob_flush().
After the entire script has finish executing, I want to save all the PHP output right from the start into a HTML file. This can be done using ob_start() and file_put_contents("log.html", ob_get_contents());
Problem: However, because we are calling ob_flush() along the way, the final file that gets saved with file_put_contents() appears to be separated into different files. I suspect this has to do with the buffer being cleared by the ob_start() calls before file_put_contents() is called, but why did it not just save the output between the final ob_flush() and file_put_contents() to the file, but instead saves several different files? (I may be wrong, the seperate partial files may be due to partial execution of the script)
In other words, how do I show PHP output as a long script executes, and still save all the PHP output to a single HTML file?
PHP Code
// Start the buffering
ob_start();
......
ob_flush();
......
ob_flush();
......
file_put_contents("log.html", ob_get_contents());
Couple of ways I can think of:
Keep a variable (called something like $content), and append the current buffer every time you call ob_flush():
$content = '';
...
$content .= ob_get_contents();
ob_flush();
...
$content .= ob_get_contents();
ob_flush();
...
file_put_contents('log.html', $content . ob_get_contents());
ob_flush();
Use fopen():
$fp = fopen('log.html', 'w+');
...
fwrite($fp, ob_get_contents());
ob_flush();
...
fwrite($fp, ob_get_contents());
ob_flush();
...
fwrite($fp, ob_get_contents());
fclose($fp);
ob_flush();
You could also use ob_get_contents() along the way, save it to a variable and then into the file and the outputstream...
You can grab the buffer contents, and store it in a a variable by calling ob_get_contents.
Have you read the manual?

How to determine whether ob_start(); has been called already

I use output buffering for gzip compression and access to what was put out before in a PHP script:
if(!ob_start("ob_gzhandler")) ob_start();
Now if that script gets included in another script where ob_start() already is in use I get a warning:
Warning: ob_start() [ref.outcontrol]: output handler 'ob_gzhandler' cannot be used twice in filename on line n
So I'd like to test whether ob_start() has already been called. I think ob_get_status() should be what I need but what is the best way to use it in testing for this?
ob_get_level returns the number of active output control handlers and ob_list_handlers returns a lift of those handlers. So you could do this:
if (!in_array('ob_gzhandler', ob_list_handlers())) {
ob_start('ob_gzhandler');
} else {
ob_start();
}
Although in general you can call ob_start any number of times you want, using ob_gzhandler as handler cannot as you would compress already compressed data.
if (ob_get_level())
echo "ob already started";
General:
if (ob_get_status()) {
// ob started
}
More specific
$status = ob_get_status();
if ($status['name']=='ob_gzhandler') {
// ob named ob_gzhandler started
}
What about using it this way?
if (ob_get_level() == 0) ob_start();

PHP command line output buffer outputs regardless of buffer settings

I have some classes I am writing unit tests for which have echoes in them. I want to suppress this output and thought ob_start() and ob_clean() would suffice, but they aren't having an effect.
public function testSomething (){
ob_start();
$class = new MyClass();
$class->method();
ob_clean();
}
I've also tried variations such as ob_start(false, 0, true); and ob_end_clean() to no avail.
What am I missing?
you may want something like this
<?php
public function testSomething (){
ob_start();
ob_implicit_flush(false); // turn off implicit flush
// Make your output below
$class = new MyClass();
$class->method();
// End of output
// store output into variable:
$output = ob_get_contents();
}
?>
Do you have implicit_flush set to true in your PHP ini? This can cause the behaviour you are seeing as it tells PHP to tell the output layer to flush itself automatically after every output block. This is equivalent to calling the PHP function flush() after each and every call to print() or echo() and each and every HTML block.
The following solves this problem for me. Without calling ob_end_clean(), the contents of the buffer remain until the script's end, where it is flushed.
ob_implicit_flush(false);
ob_start();
/*
...
... do something that pushes countent to the output buffer
...
*/
$rendered = ob_get_contents();
ob_end_clean(); // Needed to clear the buffer

Capture STDOUT from included file to variable

How to capture everything what leaves included file to variable or another file.
Output buffering is the way to go.
<?php
ob_start(); // Start buffering output
include '/path/to/file/';
$myVariable = ob_get_clean(); // Put the buffered output
// into $myVariable and clear
// the output buffer
http://www.php.net/manual/en/function.ob-start.php
http://www.php.net/manual/en/function.ob-get-clean.php
Using output buffers: http://www.php.net/manual/en/function.ob-get-contents.php

Output buffering in PHP?

I seem to be confused about PHP output buffering. I have code like this:
function return_json($obj) {
ob_get_clean();
ob_start();
header("Content-Type: application/json");
echo json_encode($obj);
exit;
}
But it doesn't seem to like the ob_get_clean(). I do that because some HTML might accidentally get generated before it gets to that point but I thought this was how you were meant to do it.
What am I missing?
To use ob_get_clean (), you have to be sure, that at some point you have ob_start ()'ed earlier. Otherwise, there’s no buffer to clean, everything is already flushed to the user agent.
Use the ob_get_level() function to see if an output buffer is active and quit it:
while (ob_get_level()) {
ob_end_clean();
}
you have to do an ob_start before all your code to catch any output before that function is called
If you just want to clean the buffer after starting output buffering with
ob_start()
use
ob_clean()
Also be aware that nothing is already being flushed with functions like echo, print_r, etc. So the first thing in your script should be ob_start(). Be sure your includes do not already send something to the browser.
ob_start needs to be called before any content is generated. Normal usage would be something like:
ob_start();
# generated content here
$content = ob_get_contents(); # $content now contains anything that has been output already
ob_end_clean();
# generate any headers you need
echo $content;
If the problem you are having is that nothing is going to output, you seem to be missing the flush method? Also, ob_end_clean() can only be called after output buffering has been started, otherwise it returns 'false'. You can't use the ob_ methods to clean up any existing headers that have already been issued, you need to make sure of that yourself.
function return_json($obj) {
ob_start();
header("Content-Type: application/json");
echo json_encode($obj);
ob_end_flush();
exit;
}

Categories