HTML
Symfony
Drupal
twig
Drupal8
DrupalDay 11

テンプレートエンジン「Twig」の変数スコープの話

プログラミング言語における変数は、宣言する場所によって有効範囲が異なり、これを変数のスコープと呼びます。

そして、Twigにも変数のスコープが存在します。

drupal8_twig.png

検証環境

  • Macbook Pro (Retina, 15-inch, Mid 2014)
  • Mac OS X 10.11.6 El Capitan
  • PHPStorm 2017.3
  • Vagrant 1.9.4
  • CentOS 7.4.1708
  • Drupal8.4.4

グローバルスコープ

通常、Twigテンプレート上で変数に値をセットした時点でグローバル変数になります。

例)setタグを使って変数に値をセットする

{% set foo = "bar" %}

テンプレートの先頭で宣言された変数は、以降のテンプレート中でどこからでもアクセス可能です。

例)グローバルスコープで宣言された変数は任意の場所からアクセス可能

{% set foo = "value" %}

{% if foo == "value" %}
  {{ foo }}
{% endfor %}

{% for item in list %}
  {{ foo }}
{% endfor %}

{% trans %}value is {{ foo }}{% endtrans %}

ローカルスコープ

forタグに関してはローカルスコープになっています。

もちろんforループ内でグローバル変数にアクセスできます。 しかし、forループ内で新たに宣言された変数はローカル変数になるため、外からはアクセスできません。

例)ローカルスコープで宣言された変数をグローバルスコープで出力してみる

{% for item in list %}
  {% set bar = "value" %}
{% endfor %}

{{ bar }}

上のコードを実行してもらえればわかりますが、画面に何も出力されません。
(Twigは未定義の変数を出力してもとくにエラーにはならないため)

Twig公式ドキュメントのsetタグの解説でもforループ内はローカルスコープが適用されている旨が説明されています。 そして実際に検証してみたところ、blockタグもローカルスコープになっているようです。

ということで、forblockの2つのタグのときは変数のスコープを気にするようにしましょう。

ローカルスコープの中でグローバル変数に値をセットした場合の動作

for / blockタグの中で、グローバル変数に値をセットした場合はグローバル変数が破棄されて、ローカル変数になります。

例)ローカルスコープにて、グローバル変数に値を再セットしてみる

{% set foo = "value01" %}

{% block block_A %}
  {% set foo = "value02" %}
{% endblock %}

{{ foo }}

上のコードを実行すると、value02が出力されるはず・・・と勘違いしがちですが、実際は画面に何も出力されません。

グローバル変数の値を書き換えたつもりが、スコープの中でグローバル変数と競合する変数名に値をセットするとそれまでの変数が破棄されるからです。

for / blockタグの中でグローバル変数の値を操作したい場合は、新たに変数を定義した上でそちらで行うようにしましょう。

参考ページ