2016-04-07 14 views
4

我有2个控制器动作,一个通过render(controller(...))函数呈现在另一个的树枝模板中。如果我在子动作中抛出一个异常,它只会在DEV模式中捕获,而不是在PRODuction中捕获,有什么想法为什么以及如何避开它?PHP/Symfony - 为什么使用Twig呈现的控制器异常不会仅在生产模式中捕获?

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

+0

您是否尝试过使用自己的异常处理程序(使用事件侦听器)? – eRIZ

+0

'app.php'已禁用调试模式? – tom10271

+0

它可能是因为调试模式而发生的,这意味着你不应该用这种方式处理异常!在当然的情况下,如上所述,您需要查找异常处理程序 –

回答

1

在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 %} 

编辑

要只捕获特定的异常,添加以下你的听众的beggining:

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

希望这帮助。

+0

是否可以仅侦听一种类型的异常?例如:RedirectException,所以我可以得到值并重定向? – Mike

+0

我编辑了我的答案给你看! – chalasr

+0

谢谢!我正在尝试它。尽管我在服务配置文件中出现错误。现在处理它。 – Mike

0

render筛选器有一个选项可用于执行此操作:ignore_errors

{{ render(controller('WebBundle:Pages:child'), {'ignore_errors': false}) }} 

默认情况下,它被设置为!$debug,所以在生产true。你可以像这样禁用它。即使在生产中,这个例外是re-throw

+0

试过这个并且完美地工作。不过,我可能会用@chalasr的其他答案去做,因为它似乎给我的代码提供了更多的灵活性。 :-)无论如何非常感谢! – Mike

+0

你真的想在生产中设置'debug:true'吗? – Federkun

+0

@Federico最灵活的选择是EventListener(我在答案中给出)。它只允许处理一些特定的异常。 – chalasr

相关问题