创建Twig过滤器以显示根据定义为条件的结果

时间:2019-03-05 13:11:44

标签: php twig

我希望根据下表显示基于给定值的文本:

  • 如果row.someProp0false,则显示“否”
  • 如果row.someProp1true,则显示“是”
  • 如果未定义row.someProp,则显示“ N / A”

我这样做的尝试如下,但是,它导致以下错误:Key "someProp" for array with keys id, name, unit, slope, intercept, type, typeName does not exist.

$filter = new \Twig_SimpleFilter('yesNoNa', function ($v) {
    return isset($v)?($v?'Yes':'No'):'N/A';
});

row.somePro|

如何最好地做到这一点?

1 个答案:

答案 0 :(得分:1)

twig中创建“简单”过滤器的问题是它没有考虑未定义的变量/属性。要解决此问题,您需要创建自己的node class,其行为与default过滤器

步骤1.向节点类注册过滤器/功能

$filter = new \Twig_SimpleFilter('yesNoNa', function ($v) {
    return isset($v)?($v?'Yes':'No'):'N/A';
}, [ 'node_class' => \MyProject\Base\Twig\Expression\Filter\YesNoNa::class);

第2步。创建节点类

namespace MyProject\Base\Twig\Expression\Filter;

class YesNoNa extends \Twig_Node_Expression_Filter_Default {
    public function __construct(\Twig_NodeInterface $node, \Twig_Node_Expression_Constant $filterName, \Twig_NodeInterface $arguments, $lineno, $tag = null)
    {
        $yesNoNa = new \Twig_Node_Expression_Filter($node, new \Twig_Node_Expression_Constant('yesNoNa', $node->getLine()), $arguments, $node->getLine());

        if ('yesNoNa' === $filterName->getAttribute('value') && ($node instanceof \Twig_Node_Expression_Name || $node instanceof \Twig_Node_Expression_GetAttr)) {
            $test = new \Twig_Node_Expression_Test_Defined(clone $node, 'defined', new \Twig_Node(), $node->getLine());
            $false = count($arguments) ? $arguments->getNode(0) : new \Twig_Node_Expression_Constant('N/A', $node->getLine());

            $node = new \Twig_Node_Expression_Conditional($test, $yesNoNa, $false, $node->getLine());
        } else {
            $node = $yesNoNa;
        }

        parent::__construct($node, $filterName, $arguments, $lineno, $tag);
    }
}

要了解有关此类的信息,我只是深入研究了源代码,以了解如何在内核中定义默认过滤器。

似乎这一行$false = count($arguments) ? $arguments->getNode(0) : new \Twig_Node_Expression_Constant('N/A', $node->getLine());将在未定义变量时定义“默认”输出。 (因此不存在)


现在在我的沙箱中使用过滤器会产生以下输出:

{% set foo = false %}
{% set bar = true %}
{% set foobar = null %}
{% set arr = { 10: 'foobar', 1: 'foo', 5 : 'bar', 'foo': 42, } %}

Foo: {{ foo | yesNoNa }}                {# No #}
Bar: {{ bar | yesNoNa }}                {# Yes #}
Undefined: {{ undefined | yesNoNa }}    {# N/A #}
Foobar: {{ foobar | yesNoNa }}          {# N/A #}
foo.bar.foo {{foo.bar.foo | yesNoNa }}  {# N/A #}
arr.foo {{ arr.foo | yesNoNa }}         {# Yes #}

这已在twig 1.X中进行了测试-可能是此解决方案要求所有使用的twig类都具有正确的名称空间,而不是twig 2.x 中的根类。