I have now found a solution using the kernelView event. This is independet of the @Template
annotation. The kernelView event fires whenever a controller action doesn't return a response object.
(This solution is based on Symfony 2.4)
event listener service:
services:
kernel.listener.route_view:
class: Acme\DemoBundle\Templating\RouteView
arguments: ["@request_stack", "@templating"]
tags:
- { name: kernel.event_listener, event: kernel.view }
event listener class:
namespace Acme\DemoBundle\Templating;
use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
class RouteView
{
protected $controller;
protected $route;
protected $templating;
function __construct(RequestStack $requestStack, $templating)
{
$this->controller = $requestStack->getCurrentRequest()->attributes->get('_controller');
$this->route = $requestStack->getCurrentRequest()->attributes->get('_route');
$this->templating = $templating;
}
public function onKernelView(GetResponseForControllerResultEvent $event)
{
$controllerAction = substr($this->controller, strrpos($this->controller, '\\') + 1);
$controller = str_replace('Controller', '', substr($controllerAction, 0, strpos($controllerAction, '::')));
$template = 'AcmeDemoBundle:' . $controller . ':' . str_replace(strtolower($controller) . '_', '', $this->route) . '.html.twig';
$response = $this->templating->renderResponse($template, $event->getControllerResult());
$event->setResponse($response);
}
}
Now the controller behaves like this:
/**
* @Route("/new", name="article_new") -> Article:new.html.twig
* @Route("/new_ajax", name="article_new_ajax") -> Article:new_ajax.html.twig
* @Method("GET")
*/
public function newAction()
{
// ...
return array();
}