I have 2 controller actions and one is rendered in a twig template of the other by render(controller(...)) function. If I throw an exception inside of the child action, it gets caught only in DEV mode and not in PRODuction, any ideas why and how to get around it?
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")) }}
Result:
Twig is a template engine for PHP and can be used without Symfony, although it is also made by SensioLabs.
Twig is a template engine for the PHP programming language. Its syntax originates from Jinja and Django templates. It's an open source product licensed under a BSD License and maintained by Fabien Potencier. The initial version was created by Armin Ronacher.
Raw is a filter, thus it does not render any output: it just trasforms it. In this case, the "trasformation" consists in setting a "safe" mark on it so that the actual rendering (performed by the {{...}} tags) will not escape it.
In Symfony applications, all errors are treated as exceptions, no matter if they are a 404 Not Found error or a fatal error triggered by throwing some exception in your code.
In a Symfony2 project, Twig catch exceptions by default in production mode.
You can configure it in order that all exceptions are thrown like in dev mode:
// app/config/config.yml
twig:
# ...
debug: true # default: %kernel.debug%
Or, configure an exception listener:
Service declaration:
// app/config/services.yml
app.exception_listener:
class: Acme\CoreBundle\Listener\ExceptionListener
arguments: [ "@templating" ]
tags:
- { name: kernel.event_listener, event: kernel.exception, method: onKernelException }
Class:
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));
}
}
Template for exception message trace/message displaying:
// 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 %}
EDIT
To catch only specific exceptions, add the following at the beggining of your listener:
// Listen only on the expected exception
if (!$event->getException() instanceof RedirectException) {
return;
}
Hope this helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With