PHP:输出缓冲回调不改变输出

4

我有一个带回调函数的输出缓冲区。当清空缓冲区时,回调函数会被执行,但是返回的字符串没有被改变。

我正在使用以下代码:

<?php
ob_start('callback');
print 'some text';
error_log(ob_get_clean());

function callback($content) {
  error_log('callback');
  return $content . ' altered'; 
}

输出:

callback
some text

我想要的是:

callback
some text altered

我错过了什么吗?我在CLI中使用的是PHP 5.3.10。

编辑:回调正在被执行。

根据PHP手册:

当输出缓冲区被刷新(发送)或清除(使用ob_flush(),ob_clean()或类似函数)或在请求结束时将输出缓冲区刷新到浏览器时,将调用该函数。


PHP手册是否提到了包括ob_get_clean()函数?你的实验强有力地证明它没有。此外,似乎缓冲区被修改了,但获取结果却没有。 - user1086498
6个回答

9

我不确定这是一个错误还是一个特性。从PHP源代码来看,我发现在调用回调函数之前,ob_get_clean的返回值已经被填充。

我看到至少有两种解决方案。第一种是手动对输出字符串进行回调处理。我认为这不需要举例说明。

第二种方法是利用堆栈输出缓冲区的可能性。由于成功刷新使用了回调函数,因此您可以将输出代码包装在额外的输出缓冲区中,并获取修改后的内容。

ob_start();

function callback($input) { return $input . " altered"; }
ob_start('callback');
echo "foo";
ob_end_flush();

$content = ob_get_clean();
ob_end_clean();
echo $content . "\n"; // prints "foo altered\n"

如果你感兴趣,可以查看 ob_get_clean 函数的源代码 (main/output.c)。你可以在 PHP 网站上获取源代码。以下是一些提示。
/* {{{ proto bool ob_get_clean(void)
   Get current buffer contents and delete current output buffer */
PHP_FUNCTION(ob_get_clean)
{
    if (zend_parse_parameters_none() == FAILURE) {
        return;
    }

    // THIS CALL FILLS THE RETURN VALUE
    if (php_ob_get_buffer(return_value TSRMLS_CC) == FAILURE) {
        RETURN_FALSE;
    }

    if (!OG(ob_nesting_level)) {
        php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer. No buffer to delete");
        zval_dtor(return_value);
        RETURN_FALSE;
    }
    if (OG(ob_nesting_level) && !OG(active_ob_buffer).status && !OG(active_ob_buffer).erase) {
        php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer %s", OG(active_ob_buffer).handler_name);
        zval_dtor(return_value);
        RETURN_FALSE;
    }

    // THIS CALL KILLS THE CURRENT BUFFER AND EXECUTES THE CALLBACK
    php_end_ob_buffer(0, 0 TSRMLS_CC);
}
/* }}} */

php_end_ob_buffer 函数获取 OB 缓冲区的内容并将回调函数应用于其中。如果第一个参数为 true,则将内容传递给下一个输出缓冲处理程序。在本例中,它为 false,因此即使执行了回调函数,但内容仍将丢失。


1
如果我要猜的话,应该是这样的。 ob_get_clean() 返回缓冲区的结果,然后清除它,触发回调函数修改内容。
例如:
从缓冲区中提取“一些文本”,根据“获取”功能的要求准备返回。
接下来,清除缓冲区,但在清除之前,根据各种 ob 函数的要求,在回调函数针对内容进行触发。
结果是缓冲区被返回(按要求),但在此之后被修改,因为获取发生在清除之前。

-1

当缓冲区被刷新时,它将被调用:

ob_start('callback');
print 'some text';
ob_end_flush();

function callback($content) {
  return $content . ' altered'; 
}

提示:它也适用于CLI。


-1

我移除了 ob_get_clean,你的代码确实可以工作。

ob_start('callback');
print 'some text';
//error_log(ob_get_clean());

$buffer = ob_get_flush();

function callback($content) {
  return $content . ' altered';
}

我已经检查了输出,发现有一些文本被警告。

为什么你使用 ob_get_clean() 方法?它会清除缓冲区。


我没有使用它,是第三方在使用。此外,有成千上万个原因。 - Bart

-1
<?php ob_start('callback'); ?>

    Foo Bar Baz

<?php
  ob_end_flush();

  function callback($content) {
    $find = "Baz";
    $replace_with = "Foo";
    return (
      str_replace($find, $replace_with, $content)
    );
  }
?>

-1

PHP 的 CLI 没有使用输出缓冲(更具体地说,缓冲与 ob_ 函数无关)。因此,您的回调被跳过。

编辑:实际上,我无法确认标准输出缓冲是否在 CLI 上可用。我建议尝试 ob_end_flush()ob_flush()flush()


当添加调试信息时,我可以看到回调正在执行。 - Bart

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接