Skip to content

Feature idea: Recursive loop #3416

Description

@kostislav

Recursive loops

Why

While it's currently possible to loop through recursive tree-like structures in Twig, it requires creating a macro, which is slightly inconvenient and hard to get right without copy-pasting. This feature would add loop recursion as a built-in feature of Twig.

Syntax

There are several ways the syntax could look, each with pros and cons. Here are two of them, I'm sure there are more:

recurse keyword

<ul>
  {% for item in tree %}
    <li>
      {{ item.title }}
      {% if item.children is not empty %}
        <ul>
          {% recurse item.children }}
        </ul>
      {% endif %}
    </li>
  {% endfor %]
</ul>

Pros: Intuitive
Cons: Requires new keyword

recurse function in the loop variable

<ul>
  {% for item in tree %}
    <li>
      {{ item.title }}
      {% if item.children is not empty %}
        <ul>
          {% loop.recurse(item.children) }}
        </ul>
      {% endif %}
    </li>
  {% endfor %]
</ul>

Pros: No new keywords
Cons: Seems like a mis-use of the loop variable; might make loops that are using the loop variable slightly less efficient unless the recursion can be optimized away if it's not used

Implementation

An immediately invoked anonymous function that calls itself recursively, probably as an entry in the context array
Both of the previous examples would render as something along these lines:

$context['loop_function'] = function($items) use (&$context) {
    foreach ($items as $item) {
        echo '<li>';
        echo $item['title'];
        if (array_key_exists('children', $item) && !empty($item['children'])) {
            echo '<ul>';
            $context['loop_function']($item['children']);
            echo '</ul>';
        }
        echo '</li>';
    }
};
echo '<ul>';
$context['loop_function']($context['tree']);
echo '</ul>';

Who

I'll be happy to work on a PR if you think this feature makes sense.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions