Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get Request object inside a Twig Extension in Symfony?

Tags:

How can one access the Request object inside Twig Extension?

namespace Acme\Bundle\Twig;

use Twig_SimpleFunction;

class MyClass extends \Twig_Extension
{
    public function getFunctions()
    {
        return array(
            new Twig_SimpleFunction('xyz', function($param) {

                 ///  here
                 $request = $this->getRequestObject();

            })
        );
    }

    public function getName() {

        return "xyz";

    }

}
like image 859
user2143356 Avatar asked Mar 29 '13 16:03

user2143356


3 Answers

As requested in the comments, here's the prefered way of injecting a request into any service. It works with Symfony >= 2.4.

Injecting the request and putting our service in the request scope is no longer recommended. We should use the request stack instead.

namespace AppBundle\Twig;

use Symfony\Component\HttpFoundation\RequestStack;

class MyClass extends \Twig_Extension
{
    private $requestStack;

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

    public function getFunctions()
    {
        $requestStack = $this->requestStack;

        return array(
            new \Twig_SimpleFunction('xyz', function($param) use ($requestStack) {
             $request = $requestStack->getCurrentRequest();
           })
        );
    }

    public function getName()
    {
        return "xyz";
    }
}

app/config/services.yml

app.twig_extension:
    class: AppBundle\Twig\MyExtension
    arguments:
        - '@request_stack'
    tags:
        - { name: twig.extension }

Docs:

  • the request stack API
  • the request stack announcement
like image 105
Jakub Zalas Avatar answered Oct 09 '22 10:10

Jakub Zalas


Register your extension as a service and give it the container service:

# services.yml

services:

    sybio.twig_extension:
        class: %sybio.twig_extension.class%
        arguments: 
            - @service_container
        tags:
            - { name: twig.extension, priority: 255 }

Then retrieve the container by your (twig extension) class constructor and then the request:

<?php 
    // Your class file:

    // ...

    class MyClass extends \Twig_Extension
    {
        /**
         * @var ContainerInterface
         */
        protected $container;

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

        /**
         * Constructor
         * 
         * @param ContainerInterface $container
         */
        public function __construct($container)
        {
            $this->container = $container;

            if ($this->container->isScopeActive('request')) {
                $this->request = $this->container->get('request');
            }
        }

        // ...

Note that testing the scope is usefull because there is no request when running console command, it avoids warnings.

That's it, you are able to use the request !

like image 22
Sybio Avatar answered Oct 09 '22 11:10

Sybio


I would suggest setting 'needs_environment' => true for your Twig_SimpleFunction, which then will add \Twig_Environment as first argument of your function. Then in your function you can find the request like this:

$request = $twig->getGlobals()['app']->getRequest();

So the whole function will look like this:

...
public function getFunctions() {
    return [
        new \Twig_SimpleFunction('xyz', function(\Twig_Environment $env) {
            $request = $twig->getGlobals()['app']->getRequest();
        }, [
            'needs_environment' => true,
        ]),
    ];
}
...
like image 45
N3m1s Avatar answered Oct 09 '22 11:10

N3m1s