我正在尝试使用动态名称设置变量。我正在使用的代码是:
{% for i in 0..2 %}
{% set foo~i = 'array'.'~i~'.'getfoo' %}
{% set bar~i = 'array'.'~i~'.'getbar' %}
{% endfor %}
我想要的变量是:
foo0
BAR0
foo1
BAR1
foo2的
bar2
但我收到此错误Unexpected token "operator" of value "~" ("end of statement block" expected)
此外,我不希望这些变量成为数组。
答案 0 :(得分:1)
就像@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"
}
但请注意,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() }}
你得到了这个 - 注意代表循环之外的“父”上下文的_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
赢了'因为它尚未初始化,所以在全局范围内:
{% set foo0 = null %}
{% set foo1 = null %}
{% set foo2 = null %}
{% for i in 1..3 %}
{% do set('foo' ~ i, 'iteration ' ~ i) %}
{% endfor %}
{{ dump() }}
以上将打印:
array(3) {
["foo0"]=>
NULL
["foo1"]=>
string(11) "iteration 1"
["foo2"]=>
string(11) "iteration 2"
}
第二种方法是修改扩展程序的set
方法,以检查$context
是否包含密钥_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(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_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
循环中使用这两种方法为已初始化的变量设置新值。