问题描述
我正在尝试使用动态名称设置变量.我使用的代码是:
I am trying to set variables with dynamic names. The code I am using is:
{% for i in 0..2 %}
{% set foo~i = 'array'.'~i~'.'getfoo' %}
{% set bar~i = 'array'.'~i~'.'getbar' %}
{% endfor %}
我想要的变量是:
foo0
栏0
foo1
栏1
foo2
栏2
The variables I want are:
foo0
bar0
foo1
bar1
foo2
bar2
但我收到此错误值~"的意外标记运算符"(预期为语句块结束")
我也不希望这些变量作为数组.
Also I don't want these variables as array.
推荐答案
就像@DarkBee 提到的那样,你不能在 vanilla Twig 中做到这一点.但是你可以创建一个非常简单的扩展 -ndash;注意 $context
需要通过引用传递:
Like @DarkBee mentioned, you can't do this in vanilla Twig. But you can create quite a simple extension – notice that $context
needs to be passed by reference:
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 中你可以:
Then in Twig you can do:
{{ dump() }}
{% do set('foo' ~ 1, 'bar') %}
{{ dump() }}
上面会打印:
array(0) {
}
array(1) {
["foo1"]=>
string(3) "bar"
}
但请注意,for
循环有其自己的上下文.所以如果你这样做:
But note that a for
loop has its own context. So if you do this:
{% 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
数组,它代表循环外的父"上下文:
You get this – notice the _parent
array which represents the "parent" context outside of the loop:
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
开始code>,并且 foo3
不会在全局上下文中,因为它尚未初始化):
You can overcome this limitation in three ways. First is to initialize the variables before the for
loop (notice that foo0
is left as null
because the loop starts at 1
, and that foo3
won't be in the global context because it hasn't been initialized):
{% 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
是否包含一个key_parent
:
The second way is to modify the extension's set
method to check whether $context
contains a key _parent
:
public function set(&$context, $name, $value) {
$context[$name] = $value;
if (array_key_exists('_parent', $context)) {
$this->set($context['_parent'], $name, $value);
}
}
那么即使是嵌套的 for
循环也不是问题:
Then even nested for
loops aren't a problem:
{% 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
:
The third way is to keep the extension's set
method intact and create a new method, e.g. 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
循环中使用这两种方法来为已经初始化的变量设置新值.
Then you can use set
to set variables in the current context (e.g. in the context of a for
loop) or set_global
to set "global" variables (in the context of the file). You can use both methods inside for
loops to set new values to already initialized variables.
这篇关于如何使用动态变量设置变量名称?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!