首页 > 解决方案 > 带有 ob_start 回调函数的 ob_get_clean

问题描述

我正在尝试使用多个 ob_start 获得缓冲输出。有些 ob_start 有回调函数。函数调用但没有效果。

<?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;

预期结果是

third
deleted
first

但我明白了

third
second
first

我做错了什么?

标签: phpbuffer

解决方案


我也对此感到惊讶,并且文档可能对此更加清楚。根据文档

ob_get_clean() 本质上同时执行 ob_get_contents() 和 ob_end_clean()。

但是,$callbackof在以下情况下ob_start($callback) 被调用

[...] 输出缓冲区被刷新(发送)或清理(使用 ob_flush()、ob_clean() 或类似函数)或在请求结束时将输出缓冲区刷新到浏览器时。

$callback被调用时ob_get_contents()已经被调用并且它对 没有影响$contents

我们可以在PHP 源代码中确认:

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);
    }
}

我不认为有办法解决这个问题。您需要小心使用ob_get_contents(). 如果要堆叠多个输出处理程序,请仅使用ob_start($callback)s. 如果可以选择调用$callbackonob_get_contents()和等效项,那肯定会很好。


推荐阅读