Pergunta

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

Foi útil?

Solução

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') %}

Outras dicas

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 :)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top