LoginSignup
0
0

式を評価、"ExpressionLanguage"

Last updated at Posted at 2023-12-08

Symfony Component Advent Calendar 2023の9日目の記事です。

式を評価、"ExpressionLanguage"

ExpressionLanguageは、文字列の式を評価してくれるコンポーネントです。Symfony以外でも使えます。

インストール

composer require symfony/expression-language

使い方

"文字列の式を評価"というのはなかなか伝わりにくいかなと思うんですが、実際のコードを見れば一目瞭然かなと思います。

use Symfony\Component\ExpressionLanguage\ExpressionLanguage;

$expressionLanguage = new ExpressionLanguage();

$resulst = $expressionLanguage->compile('3 + 2'); // (3 + 2)
$result = $expressionLanguage->evalute('3 + 2'); // 5

compile() は与えた文字列の式をPHPにコンパイルします。evaluate()はコンパイルせずに与えた文字列の式を評価して、結果を返してくれます。基本使うのはevaluate()かな。。

上記はただの算数ですが、変数を渡して評価することもできます。メソッドの呼び出しは->から.に変わります。

$apple = new Item();
$apple
  ->setName('りんご')
  ->setPrice(100)
;

$expressionLanguage = new ExpressionLanguage();
$expressionLanguage->evaluate('item.getName()', ['item' => $apple]); // りんご
$expressionLanguage->evaluate('item.getPrice() > 50', ['item' => $apple]); // true

独自構文

コンポーネントでいくつかの構文は用意していますが、独自構文も作成可能です。


$expressionLanguage = new ExpressionLanguage();
$expressionLanguage->register('isPublished', function (): string {
    return 'コンパイルした時の文字列';
}, function (array $arguments): bool {
    return $arguments['item']->getPublishedAt()->diff(new DateTimeImmutable(), true);
});

$item = new Item();
$item->setPublishedAt(new DateTimeImmutable('2023-12-01 00:00:00'));
$expressionLanguage->evaluate('isPublished()', ['item' => $item]); // true

なお、Symfonyで使う場合は、さらに以下の構文も用意されています。

なにがうれしいか

これの便利なところは、設定ファイルなどに式を記述できることで、プログラムを修正することなく安全にロジック変更することができるところです。

config/services.yaml
# キャンペーンの開始条件を設定
parameters:
    campaign_condition: "campaign.isActive() && campaign.getStartedAt().format('YmdHis') > 20231209000000"
class SomeController
{
    public function __construct(
        #[Autowire(param: 'campaign_condition') private readonly $condition)
    {
    }

    public function index(Campaign $campaign)
    {
        $expressionLanguage = new ExpressionLanguage();
        $started = $expressionLanguage->evaluate(
            $this->condition, 
            ['campaign' => $campaign]
        );

        if (!$started) {
            throw NotFoundHttpException();
        }

        return ['campaign' => $campaign];
        
    }
}

まとめ

今回はExpressionLanguageでした。Symfony以外でも使えますが、Symfonyの設定(config配下)で使うことができ、非常に柔軟に設定を行うことができるようになるコンポーネントとなっています。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0