DEV Community

Andrew Welch
Andrew Welch

Posted on • Originally published at nystudio107.com on

1 1

Twig Processing Order & Scope

Twig Processing Order & Scope

The Twig tem­plat­ing lan­guage has a lit­tle-known pro­cess­ing order & scope that is impor­tant to understand

Andrew Welch / nystudio107

Twig Code

Twig is a fan­tas­tic fron­tend tem­plat­ing lan­guage from Sen­sio Labs that’s gain­ing wide­spread adop­tion. My first expo­sure to it was in Craft CMS, but it’s being used in a num­ber of CMS’s & frame­works such as Sym­fony, Grav, Dru­pal 8, Octo­ber CMS, Bolt, etc. It can even be used in Word­Press via Tim­ber. This wide­spread use makes it a valu­able skill to master.

The rea­son Twig is gain­ing wide­spread adop­tion is that it com­bines ease of use with flex­i­bil­i­ty and pow­er. Fron­tend devel­op­ers who are com­fort­able writ­ing HTML and maybe a lit­tle JavaScript can pick up Twig very quickly.

For the most part, Twig is pret­ty straight­for­ward to learn and imple­ment. I’ll assume that you’re famil­iar with Twig; if you’re not, check out the Twig Book (skip ahead to Chap­ter 3: Twig for Tem­plate Designers).

There are, how­ev­er, two non-obvi­ous aspects of Twig: pro­cess­ing order and scope.

Twig Pro­cess­ing Order

I cre­at­ed a handy info­graph­ic on Twig Pro­cess­ing Order a bit ago, and will be div­ing in a bit deep­er here.

Twig Processing Order

Here are the code exam­ples used in the above infographic:

{{ foo }}
{% set foo = 'ruff' %}
{% include '_include' %}

{% block content %}
{% endblock %}

{% block notoverridden %}
    {{ foo }}
{% endblock %}



{% extends '_layout' %}

{% set foo = 'bar' %}

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



{% set len = foo |length %}
{% set foo = 'woof' %}
{{ foo }}

Enter fullscreen mode Exit fullscreen mode

This is a pret­ty typ­i­cal tem­plate set­up in Twig. We have a layout.twig that _includes include.twig, and a page.twig that _extends our _layout.twig template.

The inter­est­ing part here is the order in which these things are processed:

  1. The code in _page.twig that is not in a {% block %}
  2. The code in _layout.twig that is not in a {% block %}
  3. The code that is includ­ed in _include.twig
  4. The {% block %} code in _page.twig
  5. The {% block %} code in _layout.twig

Now, you may say ​“Okay, that’s great, but why does it mat­ter?” Usu­al­ly, it does­n’t. But there are sit­u­a­tions that will leave you scratch­ing your head try­ing to under­stand what’s going on if you don’t under­stand this Twig pro­cess­ing order.

The exam­ple code above would out­put the following:


bar
woof
ruff
ruff

Enter fullscreen mode Exit fullscreen mode

Is that what you expect­ed? While it may seem arbi­trary, the pro­cess­ing order is actu­al­ly done this way for a very impor­tant rea­son: we need to be able to over­ride things in our tem­plates that extend oth­er templates.

Twig Scope

Hey, wait a minute… did­n’t we change foo to 'woof' via {% set foo = 'woof' %} in the include.twig tem­plate? Why was that nev­er out­put? Let me intro­duce you to the con­cept of _scope.

Vari­ables in Twig exist only in the con­text in which they are defined. Sub­sti­tute ​‘tem­plate’ for ​‘con­text’, and you’ll prob­a­bly under­stand it a bit bet­ter. In oth­er words, if we define a vari­able in one of our tem­plates, it exists only there.

For exam­ple, if in our _include.twig tem­plate we did {% set woof = 'bark' %}, the vari­able woof will not be avail­able in our page.twig or our _layout.twig tem­plates. It’s only avail­able for use in the _include.twig tem­plate where we defined it.

Aha, but then how are we access­ing the vari­able foo (defined in our page.twig tem­plate) from the _include.twig tem­plate? The answer is that Twig pass­es down a copy of the cur­rent con­text to tem­plates that we include.

Copy is the key word here. While we can access foo in _include.twig, any changes we make to it will not be prop­a­gat­ed back up to page.twig or _layout.twig. That’s why we nev­er saw woof get out­put anywhere.

And indeed, when we include tem­plates in Twig, we can add vari­ables to the Twig con­text it will inher­it like this {% include '_include' with { 'someVar': 'someValue' } %}. We can even say we don’t want to include any of the par­ent con­text (only the val­ues we pass in) via {% include '_include' with { 'someVar': 'someValue' } only %}. Check out the Twig docs for details.

For­tu­nate­ly, tem­plates that extend oth­er tem­plates share the same con­text, so vari­ables are both acces­si­ble & change­able in this case.

Wrap­ping Up

That’s it. Twig pro­cess­ing order and scope may seem a bit eso­teric, but under­stand­ing how your tools work under the hood will save you many hours of frus­tra­tion try­ing to fig­ure out why things are not work­ing as expected.

Hap­py templating!

Further Reading

If you want to be notified about new articles, follow nystudio107 on Twitter.

Copyright ©2020 nystudio107. Designed by nystudio107

AWS Security LIVE!

Join us for AWS Security LIVE!

Discover the future of cloud security. Tune in live for trends, tips, and solutions from AWS and AWS Partners.

Learn More

Top comments (0)

AWS Q Developer image

Your AI Code Assistant

Generate and update README files, create data-flow diagrams, and keep your project fully documented. Built to handle large projects, Amazon Q Developer works alongside you from idea to production code.

Get started free in your IDE

Instrument, monitor, fix: a hands-on debugging session

Join Lazar for a hands-on session where you’ll build it, break it, debug it, and fix it. You’ll set up Sentry, track errors, use Session Replay and Tracing, and leverage some good ol’ AI to find and fix issues fast.

Tune in to the full event

DEV is partnering to bring live events to the community. Join us or dismiss this billboard if you're not interested. ❤️