Include a template that sets variables (global template variables) I'm essentially looking for a way to have a template that runs through a bunch of sets that I might use throughout my templates.

The problem is, if I include in a template with an extends, it dies up with:


  A template that extends another one cannot have a body.


{% include '/_resources/variables.twig' %}
{% extends '/_layouts/default.twig' %}


Some research indicates that maybe this isn't easily done with Twig parsing alone:
https://stackoverflow.com/questions/20410194/use-twig-custom-set-variables-from-an-include
https://groups.google.com/forum/#!topic/twig-users/QKdpWAxLdjE

So, what would be the best way to achieve this? My initial thought would be a plugin that you gave the path of a template, which preloaded things into variables.

I realize some variables (strings) could be done via macros. But, for example, I have a set usStates = {...} that is a big hash of state codes and names.
There are actually two issues with this approach. The first, and the direct reason you’re getting that Twig error, is that templates that extend another template can only output things within {% block %} tags. Any HTML that gets output outside of those tags (either directly or via {{ output tags }}) will result in that Twig error.

The {% include %} tag is in the same boat. Its only purpose (as far as the parent template is concerned) is to output the results of a child template. So like {{ output tags }}, you can’t place it outside of {% block %} tags. If you really want to include a template within these nested templates, you will need to move it to within your {% block %}.

Even if you did that, though, you’d then run into the second issue: Any variables that are set/modified within an included template will not bubble back up to the parent template. For example, if you had these two templates:


parent template:

{% include "_inc" %}
{{ foo }}

child template (_inc.html):

{% set foo = 'bar' %}



That foo variable would actually be discarded as soon as Twig was finished rendering _inc.html; nothing that happens in there will have any effect on the parent template. (As I said, the only purpose of the {% include %} tag as far as the parent template is concerned is to output the rendering result of the included template.)

However, it’s still probably possible to achieve what you want when you consider the order in which these templates are going to be processed:


Everything besides the {% block %} tags in the requested template (the one with the {% extends %} tag)
The layout template (_layouts/default.twig), including its {% block %} tags
The requested template’s {% block %} tags


Knowing that, you can probably just set your variables you’re trying to set from within _layouts/default.twig, and they will be available within the requested template’s {% block %} tags.


requested template:

{% extends '_layouts/default.twig' %}

{% block content  %}
    {{ foo }}
{% endblock %}

layout template (_layouts/default.twig):

{# Set the variables you were trying to set in _resources/variables.twig #}
{% set foo = 'bar' %}

{% block content %}
{% endblock %}