Bug #76563 [Com]: ob_get_clean does not call the ob_start callback

From: Date: Thu, 28 Nov 2019 02:04:49 +0000
Subject: Bug #76563 [Com]: ob_get_clean does not call the ob_start callback
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-223909@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=76563&edit=1

 ID:                 76563
 Comment by:         a at b dot c dot de
 Reported by:        roland at nextendweb dot com
 Summary:            ob_get_clean does not call the ob_start callback
 Status:             Open
 Type:               Bug
 Package:            Output Control
 PHP Version:        7.2.7
 Block user comment: N
 Private report:     N

 New Comment:

First of all, for reference, here is the test script from the original bug report:

<?php
function parse_output( $out ) {

	return 'Parsed: ' . $out.'<hr>';
}

ob_start( 'parse_output');
echo "asd";

$content = ob_get_clean();
echo $content;
?>

And

<?php
function parse_output( $out ) {

	return 'Parsed: ' . $out.'<hr>';
}

ob_start( 'parse_output');
echo "asd";

$content = ob_get_contents();
ob_clean();
echo $content;
?>


TL/DR; while the documentation says that the callback is used by ob_flush(), ob_clean() and similar,
the fact is the callback is only used when flushing the buffer to output. Neither discarding the
buffer's contents (ob_clean() ob_end_clean(), ob_get_clean()) nor retrieving the current buffer
contents (ob_get_contents(), ob_get_clean()) invoke the output callback.

Whether the buffer-cleaning functions _should_ invoke the output callback (keeping in mind that in
themselves they do not generate output), or whether the documentation is at fault, is the question.

Demonstrations:

The first thing to notice about the second script is that it never turns output buffering off: it
only clears the buffer's contents. There is therefore an implicit ob_flush() at the very end
that passes the buffer through the callback. Here are some variations, starting with the original
two

1:
$content = ob_get_clean();
echo strlen($content);
Output: 3
[No flushing of the output buffer occurs: its contents are retrieved, and then discarded from the
buffer, and buffering is turned off. The subsequent echo then proceeds as normally.]

2:
$content = ob_get_contents();
ob_clean();
echo strlen($content);
Output: Parsed: 3<hr>
[The contents of the buffer are retrieved and then discarded from the buffer. The buffer remains
active, however, and the subsequent echo is buffered. When the script ends, the still-active output
buffer is implicitly flushed and that flushed content is passed through the callback.]

3:
$content = ob_get_contents();
ob_end_clean();
echo strlen($content);
[ob_get_clean() should be equivalent to this. The behaviour is the same as case 1]

4:
$content = ob_get_contents();
ob_flush();
echo strlen($content);
Output: Parsed: asd<hr>Parsed: 3<hr>
[So let's flush explicitly. We retrieved the contents of the buffer ("asd") and put
it in $content. We then flushed the buffer and in doing so passed it through the callback. But we
didn't turn off buffering, so when we echoed the length of $content, it got buffered, and the
implicit flush at the end saw _that_ passed through the callback. 

5: 
$content = ob_get_contents();
ob_end_flush();
echo strlen($content);
Output: Parsed: asd<hr>3
[So let's turn off buffering before the end. Since we turned buffering off, the second echo
wasn't buffered and didn't need flushing and didn't go through the callback].


Previous Comments:
------------------------------------------------------------------------
[2019-05-29 14:27:48] calvet dot thomas at gmail dot com

Just experienced the same behavior. That looks like a bug as well to me. If you ob_end_flush()
before the ob_end_clean(), it just works..

------------------------------------------------------------------------
[2018-07-02 15:14:13] roland at nextendweb dot com

Description:
------------
If you use ob_start with callback, the callback does not run, if you use ob_get_clean() on the same
output buffer. The callback get skipped, which gives unexpected results. I think it is a bug.

Test script:
---------------
Expected output:
Parsed: asd<hr>


#1:
ob_get_clean:
http://sandbox.onlinephpfunctions.com/code/9444bc54b4311c456f7e0f26d936c55b7114417a
Output:
asd

#2 ob_get_contents + ob_clean
http://sandbox.onlinephpfunctions.com/code/f4aa458142dfdb7867d662983504689bbba191b8
Output:
Parsed: asd<hr>

Expected result:
----------------
Output:
Parsed: asd<hr>



------------------------------------------------------------------------



--
Edit this bug report at https://bugs.php.net/bug.php?id=76563&edit=1


Thread (4 messages)

« previous php.bugs (#223909) next »