Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Macros in embed tags #2442

Closed
julienfalque opened this issue Apr 10, 2017 · 8 comments · Fixed by #3012
Closed

Macros in embed tags #2442

julienfalque opened this issue Apr 10, 2017 · 8 comments · Fixed by #3012
Labels

Comments

@julienfalque
Copy link
Contributor

julienfalque commented Apr 10, 2017

Macros imported in a template are not accessible in embed tags of the same template.

With following templates:

foo.html.twig

{% import 'bar.html.twig' as bar_macros %}

{% embed 'baz.html.twig' %}
    {% block baz %}
        {{ bar_macros.bar() }}
    {% endblock %}
{% endembed %}

bar.html.twig

{% macro bar() %}
    BAR
{% endmacro %}

baz.html.twig

{% block baz %}{% endblock %}

trying to render foo.html.twig will throw an exception: Twig_Error_Runtime: Accessing Twig_Template attributes is forbidden.

The only workaround I found is to import the macros inside the embed tag. Explicitly passing bar_macros using with keyword does not help. I have this issue with Twig 2.3.0, is it the expected behavior?

@sstok
Copy link

sstok commented Apr 10, 2017

https://twig.sensiolabs.org/doc/2.x/tags/embed.html

An embed is rendered in it's own contexts, so other then passing variables it doesn't inherit anything from it's parent.

@julienfalque
Copy link
Contributor Author

This is not true: embed tags do have access to variables from the context they are declared in unless you use the only keyword, just like with include tags.

Anyway, passing the imported macro explicitly to the embed tag like this:

{% embed 'baz.html.twig' with {'bar_macros': bar_macros} %}
    {% block baz %}
        {{ bar_macros.bar() }}
    {% endblock %}
{% endembed %}

does not work either.

@julienfalque
Copy link
Contributor Author

julienfalque commented Apr 12, 2017

This also fails with macros from the same template:

{% macro bar() %}
    BAR
{% endmacro %}

{% embed 'baz.html.twig' %}
    {% import _self as bar_macros %}

    {% block baz %}
        {{ bar_macros.bar() }}
    {% endblock %}
{% endembed %}

but the error is different: Error: Call to undefined method __TwigTemplate_[...]::macro_bar().

Replacing _self with the name of the current template works.

@stof
Copy link
Member

stof commented Apr 30, 2017

@julienfalque _self refers to the anonymous template inside the {% embed %} tag, not to the main template. This is why it does not work.

@julienfalque
Copy link
Contributor Author

Wouldn't it be more convenient that _self always refers to the actual "main" template it is used in? I suppose this would be a BC break though.

@Ovissse
Copy link

Ovissse commented Mar 8, 2018

This solution seems to work

{% embed 'baz.html.twig' with {'bar': bar_macros.bar()} %}
    {% block baz %}
        {{ bar|raw }}
    {% endblock %}
{% endembed %}

@fabpot fabpot added the Macros label Apr 22, 2019
@fabpot
Copy link
Contributor

fabpot commented May 17, 2019

In #3012, I've fixed the error message to be more meaningful. #3012 already clarifies the rules. Here, you must import the macros in the embed tag.

@fabpot fabpot closed this as completed May 17, 2019
fabpot added a commit that referenced this issue May 17, 2019
…ble in macros without re-importing them (fabpot)

This PR was merged into the 2.x branch.

Discussion
----------

Macros imported "globally" in a template are now available in macros without re-importing them

closes #1790, closes #1052, closes #2414, closes #2442

Commits
-------

e138164 macros imported "globally" in a template are now available in macros without re-importing them
@carpabg
Copy link

carpabg commented Nov 13, 2021

For more complex macros or macros that it output depends on variables inside the embed block (a for loop for example) I found this solution.

{% embed 'baz.html.twig' with {'template': _self} %}
    {% import template as bar_macros %}
    {% for x in baz %}
        {{ bar(x) }}
    {% endfor %}
{% endembed %} 

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
6 participants