我在模板的代码中抛出一个异常,在模板末尾的某个地方:
...
{{ offer.throwError() }}
...
报价::throwError:
public function throwError() {
$foo = $this->getAdvantageText()->getFoo(); //fatal error
throw new 'Exception("blah"); //only exception
}
由于没有定制任何东西,我希望有一个错误页面作为响应(使用Twig的默认ExceptionController,我们实际上想覆盖它)。当Offer::getAdvantageText()为===null时,将引发FatalErrorException,并将错误页面内容直接写入引发异常的位置的标记中。当我只是抛出自定义异常时,它会按预期工作(显示一个错误页面)。当我调试到ExceptionController时,它应该明确地清除输出缓冲区:
Twig/异常控制器:
protected function getAndCleanOutputBuffering($startObLevel)
{
if (ob_get_level() <= $startObLevel) {
return '';
}
Response::closeOutputBuffers($startObLevel + 1, true);
return ob_get_clean();
}
但在我所有的致命错误情况下,ob_get_level是<=$startObLevel(由内核移交,在我的例子中是"2")。我们还没有应用程序/网关缓存。在这种情况下,当我手动清除输出缓冲区时,页面被"清除",并且我得到了一个预期的错误页面响应。据我所见,没有任何片段渲染(这会发布一个子任务)。
我曾想过利用kernel.exception事件并自行清除所有内容,但我认为只要自定义控制器就可以了。这个"致命"错误似乎干扰了Symfony内核的ob堆栈,但我不知道如何解决这个问题。
我有一个初步的解决方案来解决这个问题。在我的自定义异常控制器中,我还覆盖了getAndCleanOutputBuffering方法:
protected function getAndCleanOutputBuffering($startObLevel)
{
Response::closeOutputBuffers($startObLevel + 1, false);
return ob_get_clean();
}
如果Response::closeOutputBuffers
的第二个参数设置为false
,它将在后台调用"ob_end_clean"而不是"ob_eend_flush"。但是,已渲染的内容将丢失。