14

我正在学习 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,但在两个版本上都会产生相同的错误。

4

7 回答 7

31

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

{{ app.request.attributes.get("_controller") }}
于 2013-08-26T08:18:11.980 回答
17

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

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

于 2013-07-09T08:58:30.550 回答
6

从 Symfony 3.x 开始,服务请求被 request_stack 取代,并且 Twig 扩展声明从 Twig 1.12 开始改变。

我将纠正 Dani 的答案(https://stackoverflow.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 %}
于 2016-05-11T07:48:38.817 回答
1

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

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

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

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

如果您想在请求期间调用控制器,您可以通过_controller请求属性的键访问它

app.request.attribute.get('_controller')

将返回

Acme\AdminBundle\Controller\DefaultController::indexAction

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

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

于 2013-06-21T12:19:05.700 回答
0

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

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

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

于 2013-10-30T00:20:40.077 回答
0

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

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

于 2013-09-26T16:00:19.633 回答
-1

控制器:

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

行动:

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

请享用 ;)

于 2013-07-09T08:18:52.310 回答