Vojtěch Morávek
Vojtěch Morávek

Reputation: 93

How to define global variables for Twig templates with values coming from the DB?

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?

Upvotes: 9

Views: 4837

Answers (2)

yivi
yivi

Reputation: 47370

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> 

Upvotes: 13

GreenCat
GreenCat

Reputation: 79

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()
    {
    }
}

Upvotes: 1

Related Questions