Symfony @Template如何引用路由而不是操作名称

Symfony @Template如何引用路由而不是操作名称,symfony,annotations,routes,templating,Symfony,Annotations,Routes,Templating,我想更改@Template注释的默认行为,该注释自动呈现名为controller action的模板 因此,在ArticleController.php /** * @Route("/new", name="article_new") * @Method("GET") * @Template() */ public function newAction() { // ... return array(); } 将呈现Article/new.html.twig 我想将此更

我想更改
@Template
注释的默认行为,该注释自动呈现名为controller action的模板

因此,在
ArticleController.php

/**
 * @Route("/new", name="article_new")
 * @Method("GET")
 * @Template()
 */
public function newAction()
{
    // ...
    return array();
}
将呈现
Article/new.html.twig

我想将此更改为引用调用该操作的路由的名称,以便可以为一个操作提供多个路由,每个路由都呈现不同的模板

这就是我目前的做法(没有
@Template
):

我现在想知道是否有办法改变
@Template
的行为来实现这一点。有没有一种方法可以自定义注释,或者只是一些方法可以使其更加自动化?
有什么想法吗?

FOSRestBundle包含与
@Template
类似的功能,但是在类级别上,因为如果在类级别上使用
@View
注释

如果您希望模板文件名反映操作-名称,但不反映路由名称(与问题中要求的相反),则此功能非常有用

渲染的模板将是,即

<controller-name>/<action-name>.html.twig
在PR之前,您必须对每个方法进行注释

注释一个方法仍然可以覆盖模板、模板变量和状态代码

示例:

/**
 * @FOSRest\View(templateVar="testdata", statusCode=201)
 */
class PersonController implements ClassResourceInterface
{
    public function newAction()
    {
        return $this->formHandler->createForm();

        // template: Person/new.html.twig 
        // template variable is 'form'
        // http status: 201
    }

    public function helloAction()
    {
        return "hello";

        // template: Person/hello.html.twig
        // template variable 'testdata' 
        // http status: 201
    }

    /**
     * @FOSRest\View("AnotherBundle:Person:get", templatevar="person")
     */
    public function getAction(Person $person)
    {
        return $person;

        // template: AnotherBundle:Person:get 
        // template variable is 'person' 
        // http status: 201
    }

    /**
     * @FOSRest\View("AnotherBundle:Person:overview", templatevar="persons", statusCode=200)
     */
    public function cgetAction()
    {
        return $this->personManager->findAll();

        // template: AnotherBundle:Person:overview 
        // template variable is 'persons'
        // http status: 200
    }

    // ...
services:
    kernel.listener.route_view:
        class: Acme\DemoBundle\Templating\RouteView
        arguments: ["@request_stack", "@templating"]
        tags:
            - { name: kernel.event_listener, event: kernel.view }
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);
    }
}

我现在已经找到了一个使用kernelView事件的解决方案。这与
@模板
注释无关。每当控制器操作不返回响应对象时,就会触发kernelView事件

(此解决方案基于Symfony 2.4)

事件侦听器服务:

/**
 * @FOSRest\View(templateVar="testdata", statusCode=201)
 */
class PersonController implements ClassResourceInterface
{
    public function newAction()
    {
        return $this->formHandler->createForm();

        // template: Person/new.html.twig 
        // template variable is 'form'
        // http status: 201
    }

    public function helloAction()
    {
        return "hello";

        // template: Person/hello.html.twig
        // template variable 'testdata' 
        // http status: 201
    }

    /**
     * @FOSRest\View("AnotherBundle:Person:get", templatevar="person")
     */
    public function getAction(Person $person)
    {
        return $person;

        // template: AnotherBundle:Person:get 
        // template variable is 'person' 
        // http status: 201
    }

    /**
     * @FOSRest\View("AnotherBundle:Person:overview", templatevar="persons", statusCode=200)
     */
    public function cgetAction()
    {
        return $this->personManager->findAll();

        // template: AnotherBundle:Person:overview 
        // template variable is 'persons'
        // http status: 200
    }

    // ...
services:
    kernel.listener.route_view:
        class: Acme\DemoBundle\Templating\RouteView
        arguments: ["@request_stack", "@templating"]
        tags:
            - { name: kernel.event_listener, event: kernel.view }
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);
    }
}
事件侦听器类:

/**
 * @FOSRest\View(templateVar="testdata", statusCode=201)
 */
class PersonController implements ClassResourceInterface
{
    public function newAction()
    {
        return $this->formHandler->createForm();

        // template: Person/new.html.twig 
        // template variable is 'form'
        // http status: 201
    }

    public function helloAction()
    {
        return "hello";

        // template: Person/hello.html.twig
        // template variable 'testdata' 
        // http status: 201
    }

    /**
     * @FOSRest\View("AnotherBundle:Person:get", templatevar="person")
     */
    public function getAction(Person $person)
    {
        return $person;

        // template: AnotherBundle:Person:get 
        // template variable is 'person' 
        // http status: 201
    }

    /**
     * @FOSRest\View("AnotherBundle:Person:overview", templatevar="persons", statusCode=200)
     */
    public function cgetAction()
    {
        return $this->personManager->findAll();

        // template: AnotherBundle:Person:overview 
        // template variable is 'persons'
        // http status: 200
    }

    // ...
services:
    kernel.listener.route_view:
        class: Acme\DemoBundle\Templating\RouteView
        arguments: ["@request_stack", "@templating"]
        tags:
            - { name: kernel.event_listener, event: kernel.view }
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);
    }
}
现在,控制器的行为如下所示:

/**
 * @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();
}

我真的不明白这和我的问题有什么关系。我希望它不基于访问操作的路径,而不定义任何其他内容。我正在根据kernelView事件制定解决方案。我想我误解了这个问题-读得太快了。不过,这个答案可能对其他人仍有帮助。您希望将路由名称而不是操作名称作为模板文件名,对吗?感谢共享:)