【问题标题】:Can a Twig_SimpleFunction modify the context?Twig_SimpleFunction 可以修改上下文吗?
【发布时间】:2015-09-11 13:47:13
【问题描述】:

是否可以通过调用 Twig_SimpleFunction 来修改当前的 twig 上下文?

我注册了以下函数:

<?php
namespace Craft;

class TwiggedTwigExtension extends \Twig_Extension
{
    public function getName()
    {
      return 'Twigged';
    }

    public function getFunctions()
    {
        return array(
            'setContextVar' => new \Twig_SimpleFunction('setContextVar', array($this, 'setContextVar'), array('needs_context' => true)),
        );
    }

    public function setContextVar($context, $str, $val)
    {
        $context['context'][$str] = $val;

        var_dump(array_keys($context['context']));
    }
}

当从像{{ setContextVar('hellow', 'world') }} 这样的模板调用时,var_dump 会显示修改后的上下文。但是像{{ dump(_context|keys) }} 这样快速检查模板不会显示修改后的上下文。

我是不是走错路了?

【问题讨论】:

  • 您是否按照here 的描述正确定义了带有need_context 参数的函数?
  • 是的,我相信是的。这是一个 pastebin - pastebin.com/D8ZnKKWm

标签: php symfony templates twig


【解决方案1】:

这对于函数来说是不可能的,因为上下文不是通过引用传递的。

在你的扩展中,你甚至可以访问$context['context'],这意味着一个名为context的变量,而不是上下文本身(_context是一个特殊的变量名,用于访问模板中的上下文,但确实如此不会出现在发送给函数的上下文数组中,因为它是数组本身)。

可能有一种方法可以通过更改节点类来自定义函数编译来执行此操作。但我还没有尝试过,维护表达式语义可能会有点困难。
无论如何,我建议不要编写这样的函数。在 Twig 中分配变量没有函数语义,不能作为表达式的一部分来完成(函数当然可以在表达式中使用)。更改此语义可能会导致奇怪的行为。

【讨论】:

  • 谢谢@chris。当我得出结论这是错误的方法时,我放弃了这种方法。
  • 您可以通过将函数定义更改为 function setContextVar(&amp;$context, ...) 来通过引用传递上下文,因此现在可以更改 twig 的上下文。见here
【解决方案2】:

就像@DarkBee 在他的评论中提到的,你可以通过引用来修改上下文:

function setContextVar(&$context, ...)

但是,仅向 Twig 添加一个函数似乎不起作用(我使用的是 Twig 2.4.4):

$twig->addFunction(new Twig_Function('setContextVar', function(&$context, $name, $value) {
    $context[$name] = $value;
}, ['needs_context' => true]));

当您在 Twig 文件中使用该函数时,上下文不会被修改,您会收到以下警告:

警告:{closure}() 的参数 1 应为参考值 在 C:\...\vendor\twig\twig\lib\Twig\Environment.php(378) 中给出: eval()'d 代码在线...

相反,您需要创建一个 Twig 扩展:

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

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

然后你可以在 Twig 中使用它而不会收到警告:

{{ dump() }}
{% do setContextVar('foo', 'bar') %}
{{ dump() }}

上面的打印例如:

array(0) {
}

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-02
    相关资源
    最近更新 更多