3

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

我正在使用以下代码:

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

4

6 回答 6

8

我不确定这是错误还是功能。看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 缓冲区的内容并对其应用回调。如果第一个参数为真,它将内容传递给下一个输出缓冲处理程序。在这种情况下它是假的,所以即使它执行了回调,内容也会丢失。

于 2012-09-12T16:33:51.123 回答
1

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

ob_get_clean()正在返回缓冲区的结果,然后清理它,触发修改内容的回调。

IE

从缓冲区中提取“一些文本”并准备根据“获取”功能的要求返回。

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

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

于 2012-09-12T16:25:26.303 回答
-1

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

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

于 2012-09-12T16:03:09.050 回答
-1

刷新缓冲区时将调用它:

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

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

PS它也适用于CLI。

于 2012-09-12T16:04:04.760 回答
-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() 方法?它清理缓冲区。

于 2012-09-12T16:12:58.183 回答
-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)
    );
  }
?>
于 2012-09-12T16:26:49.210 回答