如何使用动态变量设置变量名称? [英] How to set a variable name with dynamic variables?

查看:42
本文介绍了如何使用动态变量设置变量名称?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用动态名称设置变量.我使用的代码是:

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.

这篇关于如何使用动态变量设置变量名称?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆