2012-09-12 88 views
2

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

我用下面的代码:

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

+0

是否php手册说这包括ob_get_clean()?你的实验是一个强有力的论点,说它没有。此外,似乎缓冲区正在被修改,但get的结果不是。 – 2012-09-12 16:19:54

回答

6

我不确定这是一个错误还是一个功能。查看PHP源代码,我发现返回值ob_get_clean在调用回调之前被填充。

我看到至少有两种解决方法。首先是自己手动调用输出字符串的回调。我认为这不需要例子。

其次是利用堆叠输出缓冲的可能性。由于flush成功地使用了回调函数,因此可以将输出代码封装在附加的输出缓冲区中并获取修改后的内容。

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(主/ 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

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

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

+0

我可以看到添加调试消息时正在执行回调。 – Bart

+0

输出缓冲_does_在CLI模式下工作。 – zneak

-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()方法?它清理缓冲区。

+0

我可以看到很好的理由来清理缓冲区。 – zneak

+0

我没有使用它,第三方是。还有成千上万的原因。 – Bart

1

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

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

IE

“一些文本”从缓冲器中提取,并准备返回为每的“GET”的功能要求。

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

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

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