与仅处理ob_get_clean()的结果相比,将回调传递给ob_start有什么好处?

时间:2013-02-08 05:00:13

标签: php performance coding-style output-buffering

我想知道使用这个是否有任何实际好处......

function getSomeContent() {
    ob_start(function($content) {
        // ... modify content ...
        return $content;
    }
    // ... output stuff ...
    return ob_get_clean();
}

......而不是......

function getSomeContent() {
    ob_start();
    // ... output stuff ...
    $result = ob_get_clean();
    // ... modify content ...
    return $result;
}

...

假设“输出内容”和“修改内容”部分在每种情况下都相同。关键点在于“修改内容”已改变其位置,在第一种情况下处于回调状态,在第二种情况下处于“内联”状态。

一个人的表现有益于另一个吗?例如,当第一种形式只使用一种时,第二种形式是否会制作缓冲区内容的两个副本?或者它纯粹是一种编码风格的决定?为什么选择一种形式而不是另一种形式?

我可以看到范围访问存在差异,因为封闭范围中的任何变量都可以在第二个示例的“修改内容”部分中获得,其中它们必须“传入”{{1第一个例子中的子句。事实上,这正是我通常会选择第二种形式的原因。

2 个答案:

答案 0 :(得分:2)

现在您的代码清楚了,在您的第一个示例中,您给出了两次使用$result的情况(这不是一个好主意)。

我的主要想法是:只有在需要在当前范围内使用ob_start时才使用回调来呼叫$result。你的第一个例子变成了:

ob_start(function($content) {
    // ... modify content ...
    return $content;
}
// ... output stuff ...
ob_end_clean();

在这种情况下,$result的作业是在新范围内完成的,这可以使您的代码更清晰(例如:您调用ob_start(array($this, 'method'));),而您不需要{{1你的unset在工作结束时将它从你的主要范围中解放出来(我假设你当然正在做其他事情)。

答案 1 :(得分:1)

只是为了澄清Ninsuo的正确答案。

我的两个代码示例实际产生相同的结果。实际上,将回调与ob_get_clean()结合使用是完全没用的。

这是因为当清理刷新缓冲区时会应用回调。

但是ob_get_clean()首先检索内容,然后清除缓冲区。这意味着返回的内容不是回调返回的结果,但输入传递回调。

我写了这两个简单(和hacky)脚本来演示。

这个使用ob_get_clean()并且不会产生正确的结果:

// Tests the use of callbacks with ob_get_clean().
class TestWithGetClean {
    // This variable is set when obcallback is called.
    public $foo = null;

    // The output buffer callback.
    public function obcallback($value) { 
        $this->foo = 'set';
        return $value . '(modified)'; 
    }

    // Main method.
    public function run() {
        ob_start(array($this, 'obcallback'));
        echo 'this is the output', PHP_EOL;
        return ob_get_clean();
    }
}

// Run the test with ob_get_clean().
$t = new TestWithGetClean();
echo $t->run(); // This method returns a value in this test. (But not the correct value!)
echo $t->foo, PHP_EOL;

运行它的输出是:

  

这是输出

     

文字'(modified)'不会出现在任何地方。但请注意,实例变量$foo 已设置,因此肯定会调用回调,但输出不是我原先预期的。

与使用ob_end_flush()

的比较
// Tests the use of callbacks with ob_end_flush().
class TestWithEndFlush {
    // This variable is set when obcallback is called.
    public $foo = null;

    // The output buffer callback.
    public function obcallback($value) { 
        $this->foo = 'set';
        return $value . '(modified)' . PHP_EOL; 
    }

    // Main method.
    public function run() {
        ob_start(array($this, 'obcallback'));
        echo 'this is the output', PHP_EOL;
        ob_end_flush();
    }
}

// Run the test with ob_end_flush().
$t2 = new TestWithEndFlush();
$t2->run(); // This method produces output in this test.
echo $t2->foo, PHP_EOL;

这个产生以下输出:

  

这是输出

     

(经修饰)

     

然而,这当然不是那么有用,因为输出直接发送到客户端,因此我们无法进一步操作结果。 (例如,将文本包装在Symfony HttpFoundation组件请求对象中)。