skip to Main Content

question is there – How to get results from the service in a Twig template?

Versions:
Symfony 6.1.12
PHP 8.1.6

I have the class Navigation, that returns Navigation array with the method getNavigation():

namespace AppService;

use SymfonyComponentRoutingRouterInterface;

class Navigation
{
    private RouterInterface $router;
    private array $navigation = [];

    public function __construct(RouterInterface $router)
    {
        $this->router = $router;

        $this->setNavigation();
    }

    public function setNavigation(array $nav = []): void
    {
        $this->navigation = $nav;

        if(empty($this->navigation)) {
            $this->navigation = [
                'Home' => $this->router->generate('homepage'),
                'Products' => $this->router->generate('products'),
                'Contacts' => $this->router->generate('contacts'),
            ];
        }
    }
    
    public function getNavigation(): Array
    {
        return $this->navigation;
    }
}

Now it works by calling the class in each Controller (for example:)

public function __construct(Navigation $navigation)
    {
        $this->navigation = $navigation;
    }

// #[Route('/', name: 'homepage')]
    public function index(): Response
    {
        return $this->render('home/index.html.twig', [
            'navigation' => $this->navigation->getNavigation(),
        ]);
    }

Is it possible to get access from this service in a nav.html.twig template without calling this instance everytime?

I’ve tried to save the service in services.yaml by

services:
    app.navigation:
        class: AppServiceNavigation

and then get the access by {{ app.navigation.getNavigation() }} in twig, but it does’nt work.

Thanks in advance for answers.

2

Answers


  1. There are 2 ways.

    1. Twig Global. You can set your service as a twig global. If you call that service every page that will be good.
      Symfony Twig Globals
    config/packages/twig.yaml
    twig:
    #...
    globals:
        #the value is the service's id
        navigation: '@App\Service\Navigation' // maybe service id app.navigation
    

    And use that in twig:

        {{navigation.getNavigation()}}
    
    1. Twig Runtime. You can create a runtime class and twig extension class. Then call that function in your twig lazily
      Symfony lazy twig extension

    And I think you should change service define method. Take a look Symfony services

    Login or Signup to reply.
  2. in my opinion the best way is to write a twig extension and call the service class

    https://symfony.com/doc/current/templates.html#writing-a-twig-extension

    // App/Twig/NavigationExtension.php
    namespace AppTwig;
    
    use AppServiceNavigation;
    use TwigExtensionAbstractExtension;
    use TwigTwigFunction;
    
    class NavigationExtension extends AbstractExtension
    {
        private $navigation;
    
        public function __construct(Navigation $navigation)
        {
            $this->navigation = $navigation;
        }
    
        public function getFilters(): array
        {
            return [];
        }
    
        public function getFunctions(): array
        {
            return [
                new TwigFunction('getNavigation', [$this, 'getNavigation']),
            ];
        }
    
        public function getNavigation()
        {
            return $this->navigation->getNavigation();
        }
    }
    

    in a twig template

    // templates/somewhere.html.twig
    <div>
        {{ getNavigation() }}
    </div>
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search