在 TWIG 模板中获取控制器名称

Posted

技术标签:

【中文标题】在 TWIG 模板中获取控制器名称【英文标题】:Get controller name in TWIG template 【发布时间】:2013-06-21 11:33:59 【问题描述】:

我正在学习 symfony2.3,当我尝试在 twig 模板中获取控制器名称时出现错误。

控制器:

namespace Acme\AdminBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;

class DefaultController extends Controller

    public function indexAction($name)
    
        return $this->render('AcmeAdminBundle:Default:index.html.twig', array('name' => $name));
    

在我的 TWIG 模板中:

% extends '::base.html.twig' %
% block body %
  app.request.get('_template').get('controller') 
 Hello  name !!!
% endblock %

输出:

Impossible to invoke a method ("get") on a NULL variable ("") in AcmeAdminBundle:Default:index.html.twig at line 3 

我希望输出为“默认”

我正在使用 symfony 2.3,我也尝试过 symfony 2.1,但在两个版本上都会产生相同的错误。

【问题讨论】:

但是,您为什么需要这些信息? 我想根据控制器名称为一些链接添加类。 【参考方案1】:

使用此行在 twig 中显示控制器名称:

 app.request.attributes.get("_controller") 

【讨论】:

tnx!! app.request.attributes.get("_route") 路由名称。 我想知道为什么这不是被接受和投票最多的答案,内置简单干净,怎么了?! 你需要在这样的 JS 块中使用它:% block javascripts %app.req....% endblock %【参考方案2】:

几个月前,我遇到了和你一样的问题,“谷歌搜索”我找到了一个有效的代码,并根据我的需要对其进行了调整。我们开始吧:

1 - 我们需要为此定义一个 TWIG 扩展。如果您尚未定义,我们将创建文件夹结构 Your\OwnBundle\Twig\Extension

2 - 在这个文件夹中,我们创建文件ControllerActionExtension.php,代码如下:

namespace Your\OwnBundle\Twig\Extension;

use Symfony\Component\HttpFoundation\Request;

/**
 * A TWIG Extension which allows to show Controller and Action name in a TWIG view.
 * 
 * The Controller/Action name will be shown in lowercase. For example: 'default' or 'index'
 * 
 */
class ControllerActionExtension extends \Twig_Extension

    /**
     * @var Request 
     */
    protected $request;

   /**
    * @var \Twig_Environment
    */
    protected $environment;

    public function setRequest(Request $request = null)
    
        $this->request = $request;
    

    public function initRuntime(\Twig_Environment $environment)
    
        $this->environment = $environment;
    

    public function getFunctions()
    
        return array(
            'get_controller_name' => new \Twig_Function_Method($this, 'getControllerName'),
            'get_action_name' => new \Twig_Function_Method($this, 'getActionName'),
        );
    

    /**
    * Get current controller name
    */
    public function getControllerName()
    
        if(null !== $this->request)
        
            $pattern = "#Controller\\\([a-zA-Z]*)Controller#";
            $matches = array();
            preg_match($pattern, $this->request->get('_controller'), $matches);

            return strtolower($matches[1]);
        

    

    /**
    * Get current action name
    */
    public function getActionName()
    
        if(null !== $this->request)
        
            $pattern = "#::([a-zA-Z]*)Action#";
            $matches = array();
            preg_match($pattern, $this->request->get('_controller'), $matches);

            return $matches[1];
        
    

    public function getName()
    
        return 'your_own_controller_action_twig_extension';
    

3 - 之后我们需要指定 TWIG 被识别的服务:

services:
    your.own.twig.controller_action_extension:
        class: Your\OwnBundle\Twig\Extension\ControllerActionExtension
        calls:
            - [setRequest, ["@?request="]]
        tags:
            -  name: twig.extension 

4 - 清除缓存以确保一切正常:

php app/console cache:clear --no-warmup

5 - 现在,如果我没有忘记任何事情,您将能够在 TWIG 模板中访问这两种方法:get_controller_name()get_action_name()

6 - 示例:

You are in the  get_action_name()  action of the  get_controller_name()  controller.

这将输出如下内容:你在默认控制器的索引操作中。

您也可以使用检查:

% if get_controller_name() == 'default' %
Whatever
% else %
Blablabla
% endif %

仅此而已!我希望我能帮助你,伙计:)

编辑:注意清除缓存。如果您不使用--no-warmup 参数,您可能会意识到模板中没有显示任何内容。那是因为这个 TWIG 扩展使用请求来提取控制器和动作名称。如果你“预热”缓存,Request 和浏览器请求不一样,方法可以返回''null

【讨论】:

我需要从自定义树枝扩展中获取控制器类,使用您的解决方案总是我得到You have requested a non-existent service "sensio_distribution.webconfigurator" 当然,扩展现在可以工作了,但是我需要添加一个新功能,在这个功能中我需要使用请求 我的答案是 Symfony 2.3,因为 2.4 在许多情况下请求以不同的方式处理:symfony.com/blog/new-in-symfony-2-4-the-request-stack 我希望它会帮助你。如果没有,请再次询问(或打开一个问题让我们查看您的整个代码和您想要达到的目标) 感谢 Dani,使用我发现需要使用范围的文档(我使用的是 symfony 2.4)。我用合成服务解决了这个问题:)【参考方案3】:

自 Symfony 3.x 起,service request 被 request_stack 取代,Twig Extension 声明自 Twig 1.12 起发生变化。

我会更正 Dani (https://***.com/a/17544023/3665477) 的答案:

1 - 我们需要为此定义一个 TWIG 扩展。如果您还没有定义,我们会创建文件夹结构 AppBundle\Twig\Extension

2 - 在这个文件夹中,我们创建文件ControllerActionExtension.php,代码如下:

<?php

namespace AppBundle\Twig\Extension;

use Symfony\Component\HttpFoundation\RequestStack;

class ControllerActionExtension extends \Twig_Extension

    /** @var RequestStack */
    protected $requestStack;

    public function __construct(RequestStack $requestStack)
    
        $this->requestStack = $requestStack;
    

    public function getFunctions()
    
        return [
            new \Twig_SimpleFunction('getControllerName', [$this, 'getControllerName']),
            new \Twig_SimpleFunction('getActionName', [$this, 'getActionName'])
        ];
    

    /**
     * Get current controller name
     *
     * @return string
    */
    public function getControllerName()
    
        $request = $this->requestStack->getCurrentRequest();

        if (null !== $request) 
            $pattern = "#Controller\\\([a-zA-Z]*)Controller#";
            $matches = [];
            preg_match($pattern, $request->get('_controller'), $matches);

            return strtolower($matches[1]);
        
    

    /**
     * Get current action name
     *
     * @return string
    */
    public function getActionName()
    
        $request = $this->requestStack->getCurrentRequest();

        if (null !== $request) 
            $pattern = "#::([a-zA-Z]*)Action#";
            $matches = [];
            preg_match($pattern, $request->get('_controller'), $matches);

            return $matches[1];
        
    

    public function getName()
    
        return 'controller_action_twig_extension';
    

3 - 之后我们需要指定 TWIG 被识别的服务:

app.twig.controller_action_extension:
    class: AppBundle\Twig\Extension\ControllerActionExtension
    arguments: [ '@request_stack' ]
    tags:
        -  name: twig.extension 

4 - 清除缓存以确保一切正常:

php bin/console cache:clear --no-warmup

5 - 现在,如果我没有忘记任何事情,您将能够在 TWIG 模板中访问这两个方法:getControllerName()getActionName()

6 - 示例:

您在 getControllerName() 控制器的 getActionName() 操作中。

这将输出如下内容:您在默认控制器的索引操作中。

您也可以使用检查:

% if getControllerName() == 'default' %
Whatever
% else %
Blablabla
% endif %

【讨论】:

【参考方案4】:

我真的不明白你为什么需要这个。 您最好将参数发送到您的视图中。

但如果你真的需要这种方式,这里有一个解决方案:

您的错误来自第二个get 方法

request = app.request              // Request object
NULL    = request.get('_template') // Undefined attribute, default NULL
NULL.get('controller')             // Triggers error

如果您想在请求期间调用控制器,您可以通过请求 attribute

的键 _controller 访问它
app.request.attribute.get('_controller')

会回来

Acme\AdminBundle\Controller\DefaultController::indexAction

然后你可以按照你想要的方式解析它。

请注意,这不会返回控制器实例,只返回其名称和调用的方法

【讨论】:

感谢您对我的问题感兴趣,但如果 symfony 中有内置功能,那么我应该使用它而不是解析字符串,请参阅我在网络上找到的链接 ostedesign.com/… 您的链接中的代码错误。但是不,您不能从内置的 Twig 变量中获取控制器类的 shortname (- Controller)。 app 变量是一个 Symfony\Bundle\FrameworkBundle\Templating\GlobalVariables 实例,它不会暴露其容器【参考方案5】:

获取控制器 - app.request.attributes.get('_controller') 获取操作 - app.request.attributes.get('_template').get('name')

发现于 - http://forum.symfony-project.org/viewtopic.php?f=23&t=34083

【讨论】:

【参考方案6】:

它可能会有所不同。如果您在控制器中使用注释,例如@Template("AcmeDemoBundle:Default:index"),尝试在 Twig 模板中访问 app.request.get('_template') 将返回一个字符串,例如“AcmeDemoBundle:默认:索引”。所以你可能需要像这样访问它:

% set _template = app.request.get('_template')|split(':') %
% set controller = _template[1] %
% set bundle = _template[0] %

如果你不使用注解,那么你可以使用app.request.get('_template').get('_controller')

【讨论】:

【参考方案7】:

控制器:

 app.request.attributes.get('_template').get('controller') 

行动:

 app.request.attributes.get('_template').get('name') 

享受 ;)

【讨论】:

以上是关于在 TWIG 模板中获取控制器名称的主要内容,如果未能解决你的问题,请参考以下文章

从 Symfony 请求中获取路由并将其传递给包含的 twig 文件?

Symfony2 - 在 TWIG 模板中获取当前 URL 或路由?

Twig 模板布局 Yii2 框架

twig 模板控制器对应列表

从扩展中获取当前控制器动作和 slug

从内部控制器和twig访问rest API