9

I would like to define a global variable for twig, which would be accessible from any template.

I can create a global variable in symfony's config/packages/twig.yaml, but I need it to be a value obtained from the database.

In the documentation for twig it says to use this code:

$twig = new Twig_Environment($loader);
$twig->addGlobal('name', 'value');

Where should I use this code so this varible is available for every template?

yivi
  • 42,438
  • 18
  • 116
  • 138
  • 1
    You place it inside the controller where you fetch the data, but seeing you are working in symfony you would need to access the `twig` service e.g, `$this->get('twig')->addGlobal('name', $data);` - (*I dont know the name of the service as which `twig` is registered so you would need to check your configuration*) – DarkBee Jan 10 '19 at 06:48
  • 1
    Can I put this into any controller? Will it be accessible in any template? – Vojtěch Morávek Jan 10 '19 at 07:04
  • Every controller with access to the service container, but i'm guessing pretty much every controller – DarkBee Jan 10 '19 at 07:07

2 Answers2

13

A relatively clean way of doing would be to add an event subscriber that would inject the variables globally before the controllers are instantiated.

The problem of doing in the controller, as one of the comments suggested, is that your globals wouldn't be global at all, but defined only for that controller.

You could do something like this:

// src/Twig/TwigGlobalSubscriber.php

use Doctrine\ORM\EntityManager;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Twig\Environment;

class TwigGlobalSubscriber implements EventSubscriberInterface {

    /**
     * @var \Twig\Environment
     */
    private $twig;
    /**
     * @var \Doctrine\ORM\EntityManager
     */
    private $manager;

    public function __construct( Environment $twig, EntityManager $manager ) {
        $this->twig    = $twig;
        $this->manager = $manager;
    }

    public function injectGlobalVariables( GetResponseEvent $event ) {
        $whatYouWantAsGlobal = $this->manager->getRepository( 'SomeClass' )->findBy( [ 'some' => 'criteria' ] );
        $this->twig->addGlobal( 'veryGlobal', $whatYouWantAsGlobal[0]->getName() );
    }

    public static function getSubscribedEvents() {
        return [ KernelEvents::CONTROLLER =>  'injectGlobalVariables' ];
    }
}

The DB interaction I left deliberately fuzzy, since only you know exactly what do you want to retrieve from there. But you are injecting the EntityManager on this subscriber, so it's only a matter of retrieving the appropriate repository and perform the appropriate search.

Once this is done, you could simply do from your twig templates something like:

<p>I injected a rad global variable: <b>{{ veryGlobal }}</b></p> 
yivi
  • 42,438
  • 18
  • 116
  • 138
1

Symfony 5.4

service.yml:

   App\Twig\TwigGlobalSubscriber:
        tags:
            - { name: kernel.event_listener, event: kernel.request }

SysParams - my service takes data from the database

src\Twig\TwigGlobalSubscriber.php

<?php

namespace App\Twig;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Twig\Environment;

use App\Service\SysParams;

class TwigGlobalSubscriber implements EventSubscriberInterface {

    private $twig;

    public function __construct( Environment $twig, SysParams $sysParams ) {
        $this->twig = $twig;
        $this->sysParams = $sysParams;
    }

    public function injectGlobalVariables() {
        $base_params = $this->sysParams->getBaseForTemplate();
        foreach ($base_params as $key => $value) {
            $this->twig->addGlobal($key, $value);
        }
    }

    public static function getSubscribedEvents() {
        return [ KernelEvents::CONTROLLER =>  'injectGlobalVariables' ];
    }

    public function onKernelRequest()
    {
    }
}
yivi
  • 42,438
  • 18
  • 116
  • 138
GreenCat
  • 59
  • 1
  • 5