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

时间:2012-09-12 15:59:35

标签: php output-buffering

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

我正在使用以下代码:

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

6 个答案:

答案 0 :(得分: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"

如果您感到好奇,请参阅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,则将内容传递给下一个输出缓冲处理程序。在这种情况下,它是错误的,因此即使执行回调,内容也会丢失。

答案 1 :(得分:1)

如果我有一个猜测就是这个。

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

IE

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

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

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

答案 2 :(得分:-1)

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

编辑:实际上我无法确认CLI是否提供标准输出缓冲。我会尝试ob_end_flush()ob_flush()flush()

答案 3 :(得分:-1)

刷新缓冲区时将调用它:

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

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

P.S。 它也适用于CLI。

答案 4 :(得分:-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()方法?它清理缓冲区。

答案 5 :(得分:-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)
    );
  }
?>