Twig 如何使用动态变量设置变量名?

Twig 如何使用动态变量设置变量名?,twig,Twig,我试图用动态名称设置变量。我使用的代码是: {% for i in 0..2 %} {% set foo~i = 'array'.'~i~'.'getfoo' %} {% set bar~i = 'array'.'~i~'.'getbar' %} {% endfor %} 我想要的变量是: foo0 bar0 foo1 bar1 foo2 bar2 但是我得到了这个错误值为“~”的意外标记“运算符”(“应该是语句块结尾) 另外,我不希望这些变量作为数组。就像前面提到

我试图用动态名称设置变量。我使用的代码是:

{% for i in 0..2 %}
    {% set foo~i    = 'array'.'~i~'.'getfoo' %}
    {% set bar~i    = 'array'.'~i~'.'getbar' %}
{% endfor %}
我想要的变量是:
foo0
bar0
foo1
bar1
foo2
bar2

但是我得到了这个错误
值为“~”的意外标记“运算符”(“应该是语句块结尾)


另外,我不希望这些变量作为数组。

就像前面提到的@DarkBee一样,在vanilla Twig中不能这样做。但是您可以创建一个非常简单的扩展–请注意,
$context
需要通过引用传递:

class MyTwigExtension extends Twig_Extension {
    public function getFunctions() {
        return [
            new Twig_Function('set', [$this, 'set'], ['needs_context' => true]),
        ];
    }

    public function set(&$context, $name, $value) {
        $context[$name] = $value;
    }
}
$twig->addExtension(new MyTwigExtension());
然后在Twig中,您可以执行以下操作:

{{ dump() }}
{% do set('foo' ~ 1, 'bar') %}
{{ dump() }}
以上将打印:

array(0) {
}

array(1) {
  ["foo1"]=>
  string(3) "bar"
}
array(3) {
  ["foo0"]=>
  NULL
  ["foo1"]=>
  string(11) "iteration 1"
  ["foo2"]=>
  string(11) "iteration 2"
}
array(4) {
  ["foo13"]=>
  string(7) "1 and 3"
  ["foo14"]=>
  string(7) "1 and 4"
  ["foo23"]=>
  string(7) "2 and 3"
  ["foo24"]=>
  string(7) "2 and 4"
}
但是请注意,
for
循环有自己的上下文。因此,如果您这样做:

{% set foo = 'bar' %}

Before loop:
{{ dump() }}

{% for i in 0..2 %}
    {%- do set('foo' ~ i, 'iteration ' ~ i) %}
    {%- if loop.last %}
        {{- 'Inside loop (last iteration):\n' }}
        {{- loop.last ? dump() }}
    {% endif %}
{% endfor %}

After loop:
{{ dump() }}
您可以看到这一点–请注意
\u parent
数组,它表示循环外部的“parent”上下文:

Before loop:
array(1) {
  ["foo"]=>
  string(3) "bar"
}


Inside loop (last iteration):
array(9) {
  ["foo"]=>
  string(3) "bar"
  ["_parent"]=>
  array(1) {
    ["foo"]=>
    string(3) "bar"
  }
  ["_seq"]=>
  array(3) {
    [0]=>
    int(0)
    [1]=>
    int(1)
    [2]=>
    int(2)
  }
  ["loop"]=>
  array(8) {
    ["parent"]=>
    array(1) {
      ["foo"]=>
      string(3) "bar"
    }
    ["index0"]=>
    int(2)
    ["index"]=>
    int(3)
    ["first"]=>
    bool(false)
    ["revindex0"]=>
    int(0)
    ["revindex"]=>
    int(1)
    ["length"]=>
    int(3)
    ["last"]=>
    bool(true)
  }
  ["i"]=>
  int(2)
  ["_key"]=>
  int(2)
  ["foo0"]=>
  string(11) "iteration 0"
  ["foo1"]=>
  string(11) "iteration 1"
  ["foo2"]=>
  string(11) "iteration 2"
}


After loop:
array(1) {
  ["foo"]=>
  string(3) "bar"
}
您可以通过三种方式克服此限制。首先是在
for
循环之前初始化变量(注意
foo0
保留为
null
,因为循环从
1
开始,而
foo3
由于未初始化而不在全局上下文中):

以上将打印:

array(0) {
}

array(1) {
  ["foo1"]=>
  string(3) "bar"
}
array(3) {
  ["foo0"]=>
  NULL
  ["foo1"]=>
  string(11) "iteration 1"
  ["foo2"]=>
  string(11) "iteration 2"
}
array(4) {
  ["foo13"]=>
  string(7) "1 and 3"
  ["foo14"]=>
  string(7) "1 and 4"
  ["foo23"]=>
  string(7) "2 and 3"
  ["foo24"]=>
  string(7) "2 and 4"
}
第二种方法是修改扩展的
set
方法,以检查
$context
是否包含键
\u parent

public function set(&$context, $name, $value) {
    $context[$name] = $value;

    if (array_key_exists('_parent', $context)) {
        $this->set($context['_parent'], $name, $value);
    }
}
那么,即使是嵌套的
for
循环也不是问题:

{% for i in 1..2 %}
    {% for j in 3..4 %}
        {% do set('foo' ~ i ~ j, i ~ ' and ' ~ j) %}
    {% endfor %}
{% endfor %}

{{ dump() }}
以上将打印:

array(0) {
}

array(1) {
  ["foo1"]=>
  string(3) "bar"
}
array(3) {
  ["foo0"]=>
  NULL
  ["foo1"]=>
  string(11) "iteration 1"
  ["foo2"]=>
  string(11) "iteration 2"
}
array(4) {
  ["foo13"]=>
  string(7) "1 and 3"
  ["foo14"]=>
  string(7) "1 and 4"
  ["foo23"]=>
  string(7) "2 and 3"
  ["foo24"]=>
  string(7) "2 and 4"
}
第三种方法是保持扩展的
set
方法完好无损,并创建一个新方法,例如
set\u global

class MyTwigExtension extends Twig_Extension {
    public function getFunctions() {
        return [
            new Twig_Function('set',        [$this, 'set'],        ['needs_context' => true]),
            new Twig_Function('set_global', [$this, 'set_global'], ['needs_context' => true]),
        ];
    }

    public function set(&$context, $name, $value) {
        $context[$name] = $value;
    }

    public function set_global(&$context, $name, $value) {
        $context[$name] = $value;

        if (array_key_exists('_parent', $context)) {
            return $this->set_global($context['_parent'], $name, $value);
        }
    }
}
$twig->addExtension(new MyTwigExtension());

然后,您可以使用
set
在当前上下文中设置变量(例如,在
for
循环的上下文中)或
set_global
设置“全局”变量(在文件的上下文中)。您可以在
for
循环中使用这两种方法来为已初始化的变量设置新值。

不能通过vanilla
twig
完成,您需要一个扩展