I'm trying to get buffered output with a multiple ob_start. Some ob_start has callback functions. Functions calls but with no effect.
<?php
function callback($buffer)
{
return "deleted\n";
}
ob_start();
echo "first\n";
ob_start("callback");
echo "second\n";
ob_start();
echo "third\n";
$final = '';
$levels = ob_get_level();
for ($i = 0; $i < $levels; $i++) {
$final .= ob_get_clean();
}
echo $final;
Expected result is
third
deleted
first
But I get
third
second
first
What I'm doing wrong?
I was surprised by it as well, and the documentation could be more clear about this. According to the documentation :
ob_get_clean() essentially executes both ob_get_contents() and ob_end_clean().
However, the $callback
of ob_start($callback)
is called when :
[...] the output buffer is flushed (sent) or cleaned (with ob_flush(), ob_clean() or similar function) or when the output buffer is flushed to the browser at the end of the request.
When $callback
is called ob_get_contents()
has already been called and it has no effect on $contents
.
We can confirm it in PHP source code:
PHP_FUNCTION(ob_get_clean)
{
if (zend_parse_parameters_none() == FAILURE) {
RETURN_THROWS();
}
if(!OG(active)) {
RETURN_FALSE;
}
if (php_output_get_contents(return_value) == FAILURE) {
php_error_docref("ref.outcontrol", E_NOTICE, "Failed to delete buffer. No buffer to delete");
RETURN_FALSE;
}
if (SUCCESS != php_output_discard()) {
php_error_docref("ref.outcontrol", E_NOTICE, "Failed to delete buffer of %s (%d)", ZSTR_VAL(OG(active)->name), OG(active)->level);
}
}
I don't think there's a way around this. You need to be careful with how you use ob_get_contents()
. If you want to stack multiple output handlers use only ob_start($callback)
s. It sure would be nice, if there was an option to invoke the $callback
on ob_get_contents()
and equivalents.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.