EternalHour
EternalHour

Reputation: 8621

How to access data in deeply nested Twig template?

I've just started using Twig, and I'm impressed with it compared to my custom template engine. But one thing I don't understand and am frustrated with, is how to access data once you start getting into nested includes and/or blocks.

For example, in a template I'm doing:

<!DOCTYPE html>
<html>
    <head>
        <title>Index</title>
    </head>
    <body>
        <div id="content">
        {% for section in sections %}
            <div id="sections">
              {% include 'sections.html.twig' %}
            </div>
        {% endfor %}
        </div>
    </body>
</html>

That's easy enough. But what if in sections.html.twig I have several other includes which I need to pass data to in a loop? Am I stuck building arrays with every single piece of data I need for the entire page before rendering the template?

Here's my PHP code:

$loader = new \Twig_Loader_Filesystem('path/to/templates');
$twig = new \Twig_Environment($loader);
$template = $twig->load('base.html.twig');

/*
 * Build sections array along with all other data I may need
 */

return $template->render(['sections' => $sections);

This would be easy to overcome if I could call different methods inside the template itself, but I can't. I know in Symfony you can do that, but I'm not using a framework. I hope there is something I am missing with this concept.

Upvotes: 0

Views: 523

Answers (1)

EternalHour
EternalHour

Reputation: 8621

Turns out after thinking more about ways to do this I came across the information I needed. The secret is that you CAN call custom functions/methods inside your templates.

$loader = new \Twig_Loader_Filesystem('path/to/templates');
$twig = new \Twig_Environment($loader);
$function = new \Twig_SimpleFunction('functionName', function ($arg1,$arg2) {
  return $this->class->method($arg1, $arg2);
});
$twig->addFunction($function);
$template = $twig->load('base.html.twig');

Then in your template:

{% set data = functionName('so', 'happy') %}

<div>
  // handle your data however you need //
</div>

If you don't need to iterate through it, I imagine you can also just call the function directly like {{ functionName('arg1', 'arg2') }}.

Upvotes: 0

Related Questions