Rendering templates from a Twig extension
Suppose you need to render something inside a Symfony template, like a toolbar. You could create a controller action and embed it. Symfony already explains embedded controllers in the docs, and that answer shows up often.
There is another option: create a Twig extension with a function that renders the template.
Start by creating the extension. Assume the usual AcmeDemoBundle exists in the Symfony project. This Twig extension class, similar to the one described in the Symfony docs, renders the HTML for a toolbar:
php<?php// src/Acme/DemoBundle/Twig/AcmeExtension.phpnamespace Acme\DemoBundle\Twig;class AcmeExtension extends \Twig_Extension{public function getFilters(){new \Twig_SimpleFunction('toolbar', array($this, 'renderToolbar'), array('is_safe' => array('html'))),}public function renderToolbar(){$toolbar = <<<EOF<ul class="toolbar"><li class="toolbar-item"><a href="#">Tool #1</a><li class="toolbar-item"><a href="#">Tool #2</a></ul>EOF;return $toolbar;}public function getName(){return 'acme_extension';}}
The toolbar HTML is returned from renderToolbar. It works, but the string in that method is not something I would want to maintain.
Move the HTML into a separate template:
twig<ul class="toolbar"><li class="toolbar-item"><a href="#">Tool #1</a><li class="toolbar-item"><a href="#">Tool #2</a></ul>
This template can be referenced as AcmeDemoBundle::toolbar.html.twig and rendered from the extension. You could inject the templating or twig service, but Twig can also pass the current environment into your method:
php<?php// src/Acme/DemoBundle/Twig/AcmeExtension.phpnamespace Acme\DemoBundle\Twig;class AcmeExtension extends \Twig_Extension{public function getFilters(){new \Twig_SimpleFunction('toolbar', array($this, 'renderToolbar'), array('is_safe' => array('html'),'needs_environment' => true)),}public function renderToolbar(\Twig_Environment $twig){return $twig->render('AcmeDemoBundle::toolbar.html.twig');}public function getName(){return 'acme_extension';}}
The important part is 'needs_environment' => true. It tells Twig to inject the current environment. Because this is a Symfony environment, you can use the bundle template shortcut like usual.