Get controller name in TWIG template

守給你的承諾、 提交于 2019-12-03 09:53:48

问题


I am learning symfony2.3, and I am getting an error when I try to get controller name in twig template.

Controller:

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));
    }
}

In my TWIG template:

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

Output:

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

I want output as "Default"

I am using symfony 2.3, I have also tried on symfony 2.1 but on both version generates the same error.


回答1:


use this line to display a controller name in twig:

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



回答2:


Many months ago I had the same problem as you, and "googling" I found a working code and I had adapted it to my necessities. Here we go:

1 - We need to define a TWIG extension for that. We create the folder structure Your\OwnBundle\Twig\Extension if you haven't defined yet.

2 - Inside this folder we create the file ControllerActionExtension.php which code is:

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 - After that we need to specify the service for TWIG to be recognized:

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

4 - Cache clear to make sure everything is ok:

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

5 - And now, if I'm not forgetting anything, you will be able to access those 2 methods in a TWIG template: get_controller_name() and get_action_name()

6 - Examples:

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

This will output something like: You are in the index action of the default controller.

You can also use to check:

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

And that's all!! I hope I helped you, mate :)

Edit: Take care about the clearing cache. If you don't use --no-warmup parameter maybe you will realize that nothing is shown in your templates. That's because this TWIG Extension uses the Request to extract the Controller and Action names. If you "warm up" the cache, the Request is not the same as a browser request, and the methods can return '' or null




回答3:


Since Symfony 3.x, service request is replaced by request_stack, and Twig Extension declaration changed since Twig 1.12.

I will correct the answer of Dani (https://stackoverflow.com/a/17544023/3665477) :

1 - We need to define a TWIG extension for that. We create the folder structure AppBundle\Twig\Extension if you haven't defined yet.

2 - Inside this folder we create the file ControllerActionExtension.php which code is:

<?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 - After that we need to specify the service for TWIG to be recognized:

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

4 - Cache clear to make sure everything is ok:

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

5 - And now, if I'm not forgetting anything, you will be able to access those 2 methods in a TWIG template: getControllerName() and getActionName()

6 - Examples:

You are in the {{ getActionName() }} action of the {{ getControllerName() }} controller.

This will output something like: You are in the index action of the default controller.

You can also use to check:

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



回答4:


I don't really see WHY you would need this.
You might better send parameters into your view.

But if you really need it this way, here's a solution:

Your error comes from the second get method

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

If you want to get the controller called during the request you can access it via the key _controller of the request attribute

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

Will return

Acme\AdminBundle\Controller\DefaultController::indexAction

You can then parse it the way you want.

Note that this won't return the controller instance, only its name and method called




回答5:


To get the controller - {{ app.request.attributes.get('_controller') }} To get the Action - {{ app.request.attributes.get('_template').get('name') }}

Found at - http://forum.symfony-project.org/viewtopic.php?f=23&t=34083




回答6:


It can vary. If you're using annotations in the controller, e.g. @Template("AcmeDemoBundle:Default:index"), trying to access app.request.get('_template') in your Twig template will return a string e.g. "AcmeDemoBundle:Default:index". So you might need to access it like this:

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

If you're not using annotations then you can use the app.request.get('_template').get('_controller')




回答7:


Controller:

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

Action:

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

enjoy ;)



来源:https://stackoverflow.com/questions/17234249/get-controller-name-in-twig-template

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!