0

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?

1
  • there are also global vars in twig, to which you could add your own, IF that's actually what you need. Commented May 29, 2020 at 17:09

1 Answer 1

3

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

Sign up to request clarification or add additional context in comments.

1 Comment

Ooooo! I didnt know you can do this! let me try. Thank you!!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.