duankan6894 2016-12-30 13:02
浏览 30
已采纳

扩展表达语言

I'm attempting to extend Symfony's Expression Language component so that I can use PHP's absolute value (abs) function within my expressions.

I've extended the base class and created a separate provider class for the abs function as outlined in the documentation, but the values that my class is receiving / returning isn't what I am expecting it to.

The expression that I'm trying to evaluate is as follows:

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

For example, if the result object had a timestamp of 1483100536 and the match object a timestamp of 1483014137, then you'd expect the absolute value to be 86399 and therefore for the expression to evaluate to true. However, if you use the code as it is below then the expression eventually evaluates to false as the $int value which get's passed into the evaluator function of the provider class isn't something that PHP's absolute function can handle.

The $int variable in the compiler function receives:

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

The $int variable in the evaluator function receives:

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

Now I don't truly know the inner workings of Symfony's Expression Language, but you'd like to think that it would subtract the two inner values from each other before then passing that to the outer function and then finally comparing it against the given integer.

Is there something that I need to change in my class to enable a custom function to handle expressions within itself?

Extended Base Class

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);
    }
}

Provider Class

When adding / registering a new function it is expected to have the following parts:

  • Name - The name of the function in an expression.
  • Compiler - A function executed when compiling an expression using the function.
  • Evaluator - A function executed when the expression is evaluated.

Class

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条回答 默认 最新

  • dongqintong8972 2016-12-30 15:35
    关注

    There is a difference between the parameters of the evaluator and compiler functions:

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

    As you can see, the evaluator receives a list of all available variables as the first argument. That's exactly what you discovered in the dump of $int. A fix is easy in this case, just make sure the parameters are correct:

    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);
    }),
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 微信小程序协议怎么写
  • ¥15 c语言怎么用printf(“\b \b”)与getch()实现黑框里写入与删除?
  • ¥20 怎么用dlib库的算法识别小麦病虫害
  • ¥15 华为ensp模拟器中S5700交换机在配置过程中老是反复重启
  • ¥15 java写代码遇到问题,求帮助
  • ¥15 uniapp uview http 如何实现统一的请求异常信息提示?
  • ¥15 有了解d3和topogram.js库的吗?有偿请教
  • ¥100 任意维数的K均值聚类
  • ¥15 stamps做sbas-insar,时序沉降图怎么画
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看