3

I'm trying to intercept either the rendering function or the response to add a variable to it before loading the the view(twig).

I tried to override the default render method but it still gives me

Variable "myvar" does not exist in /path/to/baseAppLite.html.twig at line 10

What's wrong with my code and is there a better way ?

This is my override code in the baseController

public function render($view, array $parameters = array(), Response $response = null)
{
    $parameters = array_merge(
        $parameters,
        array(
            'myvar' => 'GlobalVar'
        )
    );
    return parent::render($view, $parameters, $response);
}

Usage

{{ myvar }}

UPDATE: From what I can see is that the render function is not loading because i tried echoing "render bar foo" and nothing shows up

4
  • You could use the controller render method in Twig. Then you just write one small controller action which passes that global var. I'm personally not such a huge fan of overriding methods, unless there's no other way of course :) Commented May 2, 2014 at 6:41
  • @Wcool sorry for my newbie question but is there an example of that way ? how can I write a method to pass the global var other than overriding the render function through the base controller ? Commented May 2, 2014 at 7:00
  • will write an answer soon for you :) Commented May 2, 2014 at 7:02
  • Your code looks fine. Make sure your controllers are extending from your BaseController class and not the Symfony one. Commented May 2, 2014 at 12:53

2 Answers 2

3

I don't think the render function needs to be overwritten at all to be honest. I can think of a couple of ways that you could get access to some kind of global variable depending on how the global variable is set (or calculated).

Twig Globals

If it is a hardcoded variable then you could add it into your config.yml as one of the twig globals, like so...

# app/config/config.yml
twig:
    # ...
    globals:
        ga_tracking: UA-xxxxx-x

Which can then be used like...

<p>The google tracking code is: {{ ga_tracking }}</p>

As explained here - http://symfony.com/doc/current/cookbook/templating/global_variables.html

Twig Function

Alternatively if you variable is related in some way to an outside service you could use a custom twig function and call that in you template.

The twig extension (with function)..

class AcmeExtension extends \Twig_Extension
{
    protected $container;

    public function __construct(ContainerInterface $container = null)
    {
        $this->container = $container;
    }

    public function getFunctions()
    {
        return array(
            new \Twig_SimpleFilter(
                'get_parameter', 
                array($this, 'getParameter')
            ),
        );
    }

    public function getParameter($parameter)
    {
        if (null === $this->container) {
            return null;
        }

        return $this->container->getParameter($parameter);
        // You could also do perform some kind of action 
        // rather than just return a value
    }

    public function getName()
    {
        return 'acme_extension';
    }
}

Registered as a service..

services:
    acme.twig.acme_extension:
        class: Acme\DemoBundle\Twig\AcmeExtension
        arguments:
            - @service_container
        tags:
            - { name: twig.extension }

And then in your template you could use..

{{ get_parameter('myVar') }}

Or even..

{% set myVar = get_parameter('myVar') %}
Sign up to request clarification or add additional context in comments.

Comments

1

To add to my comment I have created this answer (sorry for bad grammar / spelling).

If you want to pass a var in a template that needs to be always there, you can do the following (that's how I do this anyway).

Let's say we have a PageController with CRUD methods (update, delete, show etc etc). Instead of passing that var every time (or by modifying an already defined method), we could do the following: Let Twig 'fetch' the var by rendering a controller action. Twig will call the corresponding controller and will render that variable. Let's pretend that it's a sentence in a footer that needs to be rendered by variable on each page (to keep it simple).

We could write the following action in our PageController:

public function renderFooterAction() {

    //Do your logic here, like retrieving the var from the database
    //or something completely different.
    //It could also be as easy as this:
    $myVar = "This is a footer sentence";

    //At the end we return a template
    return $this->render('AcmeDemoBundle:Page:footer.html.twig', array(
        'myVar' => $myVar,
    ));
}

The footer.html.twig page lives in YourBundle\Resources\views\Page\footer.html.twig. Depending on your needs it could be just like this (you can do everything in here like you can in a regular twig template, we're keeping it simple and only 'echoing' the variable):

{{ myVar }}

In your main template you can use the following piece of code: {{ render(controller('AcmeDemoBundle:Page:renderFooter')) }}

You can also pass parameters inside your template along if you need to when rendering a piece of it, like:

{{ render(controller('AcmeDemoBundle:Page:footer', { 'maxArticles': 5 })) }}

The above thing is assuming you want to do a for loop in the template the controller renders.

As you can see, rendering a controller in a template is almost like rendering a 'normal' view, instead of returning a whole template, you just create smaller files with only the controller responsible output.

Hope this explanation helped you a bit :) Of course, if you're still confused, just ask for more clarity.

edit: It should also be possible to directly return the variable (I think), but can't remember that so quickly. Will add that if I can find it :)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.