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 写一个方法checkPerson,入参实体类Person,出参布尔值
  • ¥15 我想咨询一下路面纹理三维点云数据处理的一些问题,上传的坐标文件里是怎么对无序点进行编号的,以及xy坐标在处理的时候是进行整体模型分片处理的吗
  • ¥15 CSAPPattacklab
  • ¥15 一直显示正在等待HID—ISP
  • ¥15 Python turtle 画图
  • ¥15 关于大棚监测的pcb板设计
  • ¥15 stm32开发clion时遇到的编译问题
  • ¥15 lna设计 源简并电感型共源放大器
  • ¥15 如何用Labview在myRIO上做LCD显示?(语言-开发语言)