2016-12-30 106 views
2

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

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

,我试图来计算表达式如下:

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

例如,如果结果对象了的1483100536时间戳和匹配对象的1483014137时间戳,那么你所期望绝对值为86399,因此表达式评估为真。但是,如果使用下面的代码,那么表达式最终会计算为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); 
    } 
} 

Provider类

当添加/注册一个新的功能,它预计将有以下几个部分:

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

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

我不知道很多关于表达式语言,但也许你可以尝试评估'result.getDate()getTimestamp() - 匹配。 .getDate()。getTimestamp()> = -86400和result.getDate()。getTimestamp() - match.getDate()。getTimestamp()<= 86400' – Brewal

回答

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