PHP/Symfony - 为什么使用 Twig 呈现的 Controller 异常不会仅在生产模式下捕获?

标签 php symfony exception try-catch

我有 2 个 Controller 操作,一个通过 render(controller(...)) 函数在另一个的 twig 模板中呈现。如果我在子操作中抛出异常,它只会在 DEV 模式下被捕获,而不会在 PRODuction 模式下被捕获,知道为什么以及如何绕过它吗?

DefaultController.php

/**
 * @Route("/test/child", name="test_child")
*/
public function childAction(Request $request)
{
    throw new \Exception($request->getRequestUri());

    return $this->render("child.html.twig");
}

/**
 * @Route("/test/parent", name="test_parent")
 */
public function parentAction(Request $request)
{
    try {
        return $this->render("parent.html.twig");
    } catch(\Exception $e)
    {
        die("got it!");
    }
}

child.html.twig

Child

parent.html.twig

Parent
<br>
{{ render(controller("WebBundle:Pages:child")) }}

结果:

enter image description here

最佳答案

在 Symfony2 项目中,Twig 在生产模式下默认捕获异常。

您可以配置它以便像在开发模式下一样抛出所有异常:

// app/config/config.yml
twig:
    # ...
    debug: true # default: %kernel.debug%

或者,配置一个异常监听器:

服务声明:

// app/config/services.yml
app.exception_listener:
    class: Acme\CoreBundle\Listener\ExceptionListener
    arguments: [ "@templating" ]
    tags:
        - { name: kernel.event_listener, event: kernel.exception, method: onKernelException }

类:

use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\Templating\EngineInterface;

class ExceptionListener
{
    private $templateEngine;

    public function __construct(EngineInterface $templateEngine)
    {
        $this->templateEngine = $templateEngine;
    }

    public function onKernelException(GetResponseForExceptionEvent $event)
    {
        $response = $this->templateEngine->render(
            'TwigBundle:Exception:error500.html.twig',
            array('status_text' => $event->getException()->getMessage())
        );
        $event->setResponse(new Response($response));
    }
}

异常消息跟踪/消息展示模板:

// app/Resources/TwigBundle/views/Exception/error500.html.twig
{% extends '::base.html.twig' %}

{% block body %}
    <div class='error'>
        <div class="message">
            <h2>Application Error</h2>
            <p>Oops! {{ status_text }}</p>
        </div>
    </div>
{% endblock %}

编辑

要仅捕获特定的异常,请在监听器的开头添加以下内容:

// Listen only on the expected exception
if (!$event->getException() instanceof RedirectException) {
    return;
}

希望这对您有所帮助。

关于PHP/Symfony - 为什么使用 Twig 呈现的 Controller 异常不会仅在生产模式下捕获?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36479226/

相关文章:

php - CodeIgniter 列表字段

symfony - 执行 "'缓存:clear --no-warmup'"command时发生错误

c# - 谷歌的 Protocol Buffer 从 C# 到 Java - 协议(protocol)消息标记的线路类型无效

php - 如何在 Php 中使用 Php?

php - 在数据库中插入图像属性

php - 在 symfony 中选择 join with doctrine

c++ - 我应该在所有异常都会导致终止的程序中使用异常处理吗?

java - 关于Cloneable接口(interface)和应该抛出的异常的问题

php - Laravel,如何确定查询构建器是否已包含 "order"?

php - 如何将完整的安全角色列表/层次结构传递给 Symfony2 中的 FormType 类?