I’m using Symfony 4.x and currently including components in Twig templates like this:
my-template.twig
{% include '/components/my-component.twig' with { data1 : some_array, data2 : some_string } %}
In the above example, my-component.twig
needs data1
and data2
to be passed into it. This means that these two data items need to be available to my-template.twig
… which means that I need to make it available in the controller that loads my-template.twig
.
class MyController extends Controller { // ... $data = [ 'data1' = [ /* some array data */ ]; 'data2' = 'a string'; ]; $res = $this->renderView('my-template.twig', $data); return new Response($res); }
The issue I’m running into is that I might use my-component.twig
in dozens of different templates, each with their own separate controllers. I will need include data1
and data2
in each one of those controllers separately just for the sake of my-component.twig
.
I have gotten around this somewhat by including common data objects in a service and including that service in all the controllers that need a particular piece of data, but this isnt ideal either.
What would be ideal is if a particular Twig component was completely self-encapsulated – meaning that I can freely include it in a template and it would automatically grab all of it’s own data. That is, the component has it’s own dedicated “controller” i.e. PHP code that automatically runs anytime a particular Twig template (component) is rendered without having to indicate this explicitely.
Is something like this possible in Symfony?
Advertisement
Answer
If I understand correctly you want to use #render() method in twig.
You create a method in your controller, i.e myComponentRender() and then you could do this instead of doing include
{{ render(controller( 'App\Controller\MyController::myComponentRender', { 'foo': 'bar' } )) }}
I have included the foo parameter just to show you it’s possible to pass a paremeter if you needed to (if you wanted to distinguish which page is calling it for example), but you likely do not need to pass anything judging by your example
To clarify, in your myComponentRender() method you need to return $this->render(…)
here’s a link actually https://symfony.com/doc/4.1/templating/embedding_controllers.html