扩展表达语言

时间:2016-12-30 13:02:40

标签: php symfony

我正在尝试扩展Symfony的表达式语言组件,以便我可以在表达式中使用PHP的absolute value (abs)函数。

我扩展了基类,并为documentation中概述的abs函数创建了一个单独的提供者类,但是我的类接收/返回的值并不是我所期望的。

我正在尝试评估的表达式如下:

abs(result.getDate().getTimestamp() - match.getDate().getTimestamp()) <= 86400

例如,如果结果对象的时间戳为1483100536,匹配对象的时间戳为1483014137,那么您希望绝对值为86399,因此表达式的计算结果为true。但是,如果你使用下面的代码,那么表达式最终会计算为false,因为传递给提供者类的赋值函数的$int值不是PHP的绝对函数可以处理的。

编译器函数中的$int变量接收:

 ($result->getDate()->getTimestamp() - $match->getDate()->getTimestamp())

评估器函数中的$int变量接收:

[
  "result" => Result {#1754}
  "match" => Match {#2161}
]`

现在我并不真正了解Symfony的表达式语言的内部工作原理,但是您想要在将其传递给外部函数然后最终将其与之对比之前将它们相互减去两个内部值。给定的整数。

我的类中是否需要更改某些内容才能启用自定义函数来处理自身内部的表达式?

扩展基类

namespace AppBundle\Service\ExpressionLanguage;

use Symfony\Component\ExpressionLanguage\ExpressionLanguage as BaseExpressionLanguage;

class ExpressionLanguage extends BaseExpressionLanguage
{
    public function __construct($cache = null, array $providers = [])
    {
        // prepend the default provider to let users override it easily
        array_unshift($providers, new StringExpressionLanguageProvider());

        parent::__construct($cache, $providers);
    }
}

提供商类

添加/注册新功能时,预计会有以下部分:

  • 名称 - 表达式中函数的名称。
  • 编译器 - 使用该函数编译表达式时执行的函数。
  • 评估者 - 评估表达式时执行的函数。

namespace AppBundle\Service\ExpressionLanguage;

use Symfony\Component\ExpressionLanguage\ExpressionFunction;
use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;

class StringExpressionLanguageProvider implements ExpressionFunctionProviderInterface
{
    public function getFunctions()
    {
        return [
            new ExpressionFunction('abs', function ($int) {
                return sprintf('(is_int(%1$d) ? abs(%1$d) : %1$d)', $int);
            }, function ($int) {
                if (!is_int($int)) {
                    return $int;
                }

                return abs($int);
            }),
        ];
    }
}

1 个答案:

答案 0 :(得分:3)

评估程序和编译器函数的参数之间存在差异:

Compiler:  function ($value) { }
Evaluator: function (array $variables, $value) { }

如您所见,评估者收到所有可用变量的列表作为第一个参数。这正是您在$int转储中发现的内容。在这种情况下,修复很容易,只需确保参数正确:

new ExpressionFunction('abs', function ($int) {
    return sprintf('(is_int(%1$d) ? abs(%1$d) : %1$d)', $int);
}, function (array $variables, $int) {
    if (!is_int($int)) {
        return $int;
    }

    return abs($int);
}),
相关问题