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


PHP: Output buffer callback not altering output

我有一个带回调函数的输出缓冲区。然而,当清理缓冲区时,回调函数会被执行,返回的字符串不会被更改。

我使用以下代码:

<?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()或类似函数),或者输出缓冲区在请求结束时被刷新到浏览器。

我不确定这是一个bug还是一个功能。查看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,因此即使执行了回调,内容也会丢失。

如果我有一个猜测,它会是这样的。

ob_get_clean()返回缓冲区的结果,THEN清除缓冲区,触发修改内容的回调。

IE

从缓冲区中提取"some text",并准备根据"get"功能的要求返回。

接下来,将清理缓冲区,但在清理之前,将根据存在回调时各种ob函数的要求,对内容触发回调。

结果是缓冲区被返回(根据请求),但在之后被修改,因为get发生在clean之前。

刷新缓冲区时会调用它:

ob_start('callback');
print 'some text';
ob_end_flush();
function callback($content) {
  return $content . ' altered'; 
}

第页。S它也适用于CLI。

PHP的CLI不使用输出缓冲(或者更具体地说,缓冲与ob_函数无关)。所以你的回拨被跳过了。

EDIT:事实上,我在确认CLI是否提供标准输出缓冲时遇到了问题。我会尝试ob_end_flush()ob_flush()flush()

我删除了ob_get_clean,您的代码就可以工作了。

ob_start('callback');
print 'some text';
//error_log(ob_get_clean());
$buffer = ob_get_flush();
function callback($content) {
  return $content . ' altered';
}

我已经检查了输出,它收到了一些文本警报。

为什么使用obgetclean()方法?它会清理缓冲区。

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