Skip to content
Advertisement

Component-level controller in Twig with Symfony PHP

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

User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement