# macros.html.twig
{% macro error_main_error(message) %}
<b>{{ message }}</b>
{% endmacro %}
# template.html.twig
{% import "macros.html.twig" as macro_helper %}
{{ macro_helper.error_main_error("Some message") }}
Triggers the following exception
(Twig_Error_Runtime(code: 0): Accessing Twig_Template attributes is forbidden.
Is this not possible anymore in 2.x?
The example you gave here works fine on Twig 2.0: https://twigfiddle.com/91rlep
:( let me check a bit
I'm not sure but it seem like this error appears if the macros are imported in a parent template and then a macro is used in a template, that is included in the parent.
Is this intended?
Update: https://twigfiddle.com/91rlep/3
It is working in twig 1.30.0 https://twigfiddle.com/91rlep/4
Yes, my case is very similar to @Findus23 , i'm using template inheritance
https://twigfiddle.com/91rlep/5 2.0 not working
https://twigfiddle.com/91rlep/6 1.30 working
( @stof did not know about twigfiddle.com, sorry if the first issue description was not accurate)
Well, for template inheritance, this is indeed not supported in Twig 2, because the child template does not know that macro_helper is a set of imported macros, as it does not have the import statement for it. Twig 1.x was triggering deprecation warnings for these cases (even though twigfiddle does not display them yet, see https://github.com/ninsuo/twigfiddle/issues/23 about that).
You need to import macros in templates using them instead.
The fact that Twig 1.x was allowing to access imported macros through the object attribute system was a left-over of the initial macro implementation, and could not be removed because this implementation detail made them accessible through inheritance (or non-guarded includes), which was never expected to work (IIRC, it was discovered by maintainers when breaking it in a release due to a refactoring of macros).
And this fact forced macros to stay implemented in a restrictive way, preventing to fix other issues related to macros. This is why we forbid this case in 2.0, allowing us to refactor the way macro work internally (the first benefit was the removal of a bunch of forbidden names for macros, but more benefits are expected to come in future 2.x releases when reworking macros internally)
I see. The update performed by symfony from twig 1.x to 2.x (running just composer update) with such kind of "difference" should be a bit more explicit.
If we are talking of "inheritance" then I expect to "inherit" from the parent "everything" marked as not private.
{% import "macros.html.twig" as macro_helper %}
vs
{% import private "macros.html.twig" as macro_helper %}
# last one is a non existent syntax, but here just for clarity
@goetas Symfony allows both 1.x and 2.x since quite some time. The difference is that composer only allows to use stable versions by default, and Twig 2.0 was released yesterday, so your project was not using Twig 2 before. Symfony was showing the deprecation warnings of Twig 1 in the profiler though.
The issue with your idea is that macro calls must be detected as such at compile time, as they need a different treatment that attribute access on a context variable (otherwise, we have to give up macro performance improvement did since 2 years, and reject any improvements to macros listed in the issue tracker, and so on).
And a template cannot access its parent at compile time (the parent can even change dynamically at runtime). All it can know at compile time is whether it has a parent or no.
the parent can even change dynamically at runtime
remember that. then makes sense importing macros explicitly. just my "upgrade" experience was a bit traumatic :)
Alright, everything clear. Now I have to decide if "refactoring" all the templates of my app, or forcing it to twig 1.x.
Thanks
@goetas Macros are indeed the darkest aspect of Twig and we know that the current situation is far from being ideal. Sorry that yo experienced it the hard way.
Hi there,
If you come back to https://twigfiddle.com/91rlep/4 the deprecation notice now appears.
Cheers,
@ninsuo Thanks! Great job! Could you make it perhaps a bit more visible?
Just updated. I'm not quite a good UX so please tell me if it seems ok now.
That's much better. Would it be possible to move the deprecations above the rendered output. On my screen (13'' laptop), the deprecations are below the fold.
IMO, result is more important than deprecations. Are you sure you want to push up this box?
Right, what about adding a "Show deprecations" button with a warning icon after "Show raw result" that would jump to the list of deprecation notices?
Done. It doesn't make lots of sense on large screens but doesn't disturb anyway.
Can we pin this up to the top.
IMO there is a lot of us who were importing the macros used almost everywhere into the topmost template. And fixing this is annoying 90% of my templates need adding import "general" and "form" twig files with macros.
And this issue is going to pop up a lot in coming months as people will run composer update
Not sure if we can "pin" this issue. But even better would be to describe the problem in the deprecated file to help people upgrade their project. Who would have time to propose a PR on that topic?
I've posted a short answer to the issue here: http://stackoverflow.com/q/41590051/1668200
First, and as shown in Twig Fiddle now, you should fix all deprecations before upgrading to Twig 2.0. That's explained in the deprecated document (first item).
I've also just added a small section about macros to describe this specific issue (see c9a14464).
Why would this error be showing up on the line 1 {% extends 'base.html.twig' %}
@tlorens: I've updated the answer for extends:
http://stackoverflow.com/a/41590052/1668200
@fabpot we seems to have an issue regarding the location of errors if they end up on the extends tag. Aren't we providing the error location directly in the error almost everywhere now ? Then why would we put it there ?
@ThomasLandauer I found the issue.. It was exactly what @stof just mentioned. The issue was about 3 templates deep (I forget). But the error message was a little mis-leading and I had to step through my templates until I figured it out. We're all good now. Thanks for the reply/and your time.
How does importing work with embed in Twig 2.x? How can I rewrite this template, which works in Twig 1.x (with a deprecation message): https://twigfiddle.com/91rlep/14
The docs for import say, "to import macros from the current file, use the special _self variable for the source." But if I move the import into the extends tag, it fails with a Call to undefined method error.
The body of an {% embed %} block is a separate template, so its imports are separate (as are its block definitions). So you should import the macro inside the nested template: https://twigfiddle.com/91rlep/15
Thanks @stof, that makes sense and fixed my issue.
Most helpful comment
@goetas Macros are indeed the darkest aspect of Twig and we know that the current situation is far from being ideal. Sorry that yo experienced it the hard way.