Search code examples
phpoutput-buffering

Looping on Output Buffers


I am seeing some behavior from ob_start() and ob_end_*() that seems very counterintuitive.

In the spirit of neatness, my algorithm is:

  1. Open buffer
  2. Do some things
  3. Save the buffer to a string
  4. Close the buffer

I'm getting the following notices at runtime for each loop case beyond the first case.

Notice: ob_end_clean(): failed to delete buffer. No buffer to delete in C:...\testing\TestOBError.php on line 21

Notice: ob_end_clean(): failed to delete buffer. No buffer to delete in C:...\testing\TestOBError.php on line 21

Notice: ob_end_clean(): failed to delete buffer. No buffer to delete in C:...\testing\TestOBError.php on line 21

Current story payload: `one'.

Current story payload: `two'.

Current story payload: `three'.

Current story payload: `four'.

Example code (TestOBError.php):

<?php
class Story {
    public $payload;
    public function __construct($payload) {
        $this->payload = $payload;
    }
}

$stories = array();
$stories[] = new Story('one');
$stories[] = new Story('two');
$stories[] = new Story('three');
$stories[] = new Story('four');

$foo = "";

foreach ($stories as $story) {
    ob_start();
    require 'TestOBError_Foo.php';
    $foo .= ob_get_clean();
    ob_end_clean();
}

print $foo;

?>

Contents of TestOBError_Foo.php:

<p>Current story payload: `<?php print $story->payload; ?>'.</p>

Am I just misusing the output buffer? Can anyone tell me the "right way" to do this?

I am running PHP version 5.4.7.


Solution

  • You don't need to call both ob_get_clean() and ob_end_clean(). Either do this:

    $foo .= ob_get_clean();
    

    Or do this:

    $foo .= ob_get_contents();
    ob_end_clean();
    

    From the PHP manual:

    string ob_get_clean ( void )

    Gets the current buffer contents and delete current output buffer.

    ob_get_clean() essentially executes both ob_get_contents() and ob_end_clean().