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

Bar*_*art 2 php output-buffering

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

我正在使用以下代码:

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

function callback($content) {
  error_log('callback');
  return $content . ' altered'; 
}
Run Code Online (Sandbox Code Playgroud)

输出:

callback
some text
Run Code Online (Sandbox Code Playgroud)

我想要的是:

callback
some text altered
Run Code Online (Sandbox Code Playgroud)

我错过了什么?我在CLI中使用PHP 5.3.10.

编辑:正在执行回调.

从PHP手册:

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

zne*_*eak 7

我不确定这是一个错误还是一个功能.查看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"
Run Code Online (Sandbox Code Playgroud)

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);
}
/* }}} */
Run Code Online (Sandbox Code Playgroud)

php_end_ob_buffer获取OB缓冲区的内容并将回调应用于它.如果第一个参数为true,则将内容传递给下一个输出缓冲处理程序.在这种情况下,它是错误的,因此即使执行回调,内容也会丢失.