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