|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2018-07-02 15:14 UTC] 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> PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Wed Oct 29 10:00:01 2025 UTC |
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].