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;
}
Related
I've reinstalled Apache, and switched from PHP 5.3 to 5.6. Everything works, except I get this error, when calling ob_start():
Cannot use output buffering in output buffering display handlers
I tried to enable output buffering in PHP, but I still get this error:
output_buffering = 4096
You're trying to start a output buffer inside a buffer callback. If you use this code, it will generate that error. But if you remove the ob_start() from the callback function it's OK.
<?php
error_reporting(-1);
function callback($buffer){
//you can't call ob_start here
ob_start();
return (str_replace("apples", "oranges", $buffer));
}
ob_start("callback");
?>
<html>
<body>
<p>It's like comparing apples to oranges.</p>
</body>
</html>
<?php
ob_end_flush();
Even though this is an old question, I just wanted to add that the same error occurs when the system runs out of memory while buffering.
If this is the case, the error mentioned in this topic will always be followed by an Allowed memory size of xxx bytes exhausted error.
Probably you are using a buffering function in output buffering callback which isn't possible as mentioned in php ob_start output_callback documentation. If not it should be the output-handler you used, check your php.ini and try to set it's value to "none" if possible.
maybe this sample code can help you:
ob_start();
echo "test";
$content = ob_get_contents();
ob_end_clean();
var_dump($content);
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();
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
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
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;