2

我想知道使用它是否有任何真正的好处......

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

...?

假设“输出内容”和“修改内容”部分在每种情况下都是相同的。关键是“修改内容”的位置发生了变化,第一种情况是在回调中,第二种情况是“内联”。

一个比另一个有性能优势吗?例如,当第一种形式只使用一个时,第二种形式是否会复制两个缓冲区内容?还是纯粹是编码风格决定?为什么会选择一种形式而不是另一种形式?

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

4

2 回答 2

2

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

我的主要想法是:仅当您不需要在当前范围内使用ob_start时才使用回调调用。您的第一个示例变为:$result

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

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

于 2013-02-08T07:08:04.263 回答
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 组件请求对象中)。

于 2013-02-14T15:30:38.300 回答