Bug #76563 [Com]: ob_get_clean does not call the ob_start callback
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)