2016-12-30 8 views
2

私は式の中でPHPのabsolute value (abs)関数を使用できるようにSymfonyの式言語コンポーネントを拡張しようとしています。式言語を拡張する

documentationで概説されているように、基底クラスを拡張し、abs関数用に別のプロバイダクラスを作成しましたが、私のクラスが受け取っている/戻っている値は、私が期待している値ではありません。

次のように私は評価しようとしている式がある:結果オブジェクトが1483100536のタイムスタンプを持っていた場合

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

例えば、試合が1483014137のタイムスタンプをオブジェクト、そしてあなたが期待絶対値は86399であるため、式は真と評価されます。しかし、コードを以下のように使用すると、プロバイダのクラスの評価関数に渡される$intの値は、PHPの絶対関数が処理できる値ではないため、式は最終的にfalseに評価されます。

コンパイラ機能で$int変数が受け取る:

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

評価関数の$int変数が受け取る:

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

今私は本当にsymfonyの式言語の内部の仕組みを知りませんしかし、2つの内部値を互いに減算してから、それを外部関数に渡してから、最後にそれを指定された整数と比較すると考えるとよいでしょう。

カスタム関数で式を処理できるようにするために、クラス内で変更が必要なことはありますか?

拡張基本クラス

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

私は表現言語について多くを知らないが、多分あなたは 'result.getDate()getTimestamp()を評価しようとすることができ - 試合を。 。getDimest()。getTimestamp()<= 86400'。getDimest()。getTimestamp()> = -86400とresult.getDate()。 – 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); 
}), 
関連する問題