Extending the ExpressionLanguage

The ExpressionLanguage can be extended by adding custom functions. For instance, in the Symfony Framework, the security has custom functions to check the user's role.

ExpressionLanguage は、カスタム関数を追加することで拡張できます。たとえば、Symfony フレームワークでは、セキュリティにユーザーのロールをチェックするためのカスタム関数があります。

Note

ノート

If you want to learn how to use functions in an expression, read "The Expression Syntax".

式で関数を使用する方法を学びたい場合は、「式の構文」を読んでください。

Registering Functions

Functions are registered on each specific ExpressionLanguage instance. That means the functions can be used in any expression executed by that instance.

関数は、特定の ExpressionLanguage インスタンスごとに登録されます。つまり、関数は、そのインスタンスによって実行される任意の式で使用できます。

To register a function, use register(). This method has 3 arguments:

関数を登録するには、register() を使用します。このメソッドには 3 つの引数があります。
  • name - The name of the function in an expression;
    name - 式内の関数の名前。
  • compiler - A function executed when compiling an expression using the function;
    compiler - 関数を使用して式をコンパイルするときに実行される関数。
  • evaluator - A function executed when the expression is evaluated.
    evaluator - 式が評価されるときに実行される関数。

Example:

例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;

$expressionLanguage = new ExpressionLanguage();
$expressionLanguage->register('lowercase', function ($str) {
    return sprintf('(is_string(%1$s) ? strtolower(%1$s) : %1$s)', $str);
}, function ($arguments, $str) {
    if (!is_string($str)) {
        return $str;
    }

    return strtolower($str);
});

var_dump($expressionLanguage->evaluate('lowercase("HELLO")'));
// this will print: hello

In addition to the custom function arguments, the evaluator is passed an arguments variable as its first argument, which is equal to the second argument of evaluate() (e.g. the "values" when evaluating an expression).

カスタム関数の引数に加えて、エバリュエーターには引数変数が最初の引数として渡されます。これは、evaluate() の 2 番目の引数と同じです (たとえば、式を評価するときの「値」)。

Using Expression Providers

When you use the ExpressionLanguage class in your library, you often want to add custom functions. To do so, you can create a new expression provider by creating a class that implements ExpressionFunctionProviderInterface.

ライブラリで ExpressionLanguage クラスを使用する場合、カスタム関数を追加したいことがよくあります。そのために、ExpressionFunctionProviderInterface を実装するクラスを作成して、新しい式プロバイダーを作成できます。

This interface requires one method: getFunctions(), which returns an array of expression functions (instances of ExpressionFunction) to register:

このインターフェイスには、登録する式関数 (ExpressionFunction のインスタンス) の配列を返す getFunctions() メソッドが 1 つ必要です。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
use Symfony\Component\ExpressionLanguage\ExpressionFunction;
use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;

class StringExpressionLanguageProvider implements ExpressionFunctionProviderInterface
{
    public function getFunctions()
    {
        return [
            new ExpressionFunction('lowercase', function ($str) {
                return sprintf('(is_string(%1$s) ? strtolower(%1$s) : %1$s)', $str);
            }, function ($arguments, $str) {
                if (!is_string($str)) {
                    return $str;
                }

                return strtolower($str);
            }),
        ];
    }
}

Tip

ヒント

To create an expression function from a PHP function with the fromPhp() static method:

fromPhp() 静的メソッドを使用して PHP 関数から式関数を作成するには:
1
ExpressionFunction::fromPhp('strtoupper');

Namespaced functions are supported, but they require a second argument to define the name of the expression:

名前空間関数はサポートされていますが、式の名前を定義するために 2 番目の引数が必要です。
1
ExpressionFunction::fromPhp('My\strtoupper', 'my_strtoupper');

You can register providers using registerProvider() or by using the second argument of the constructor:

registerProvider() を使用するか、コンストラクターの 2 番目の引数を使用して、プロバイダーを登録できます。
1
2
3
4
5
6
7
8
9
10
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;

// using the constructor
$expressionLanguage = new ExpressionLanguage(null, [
    new StringExpressionLanguageProvider(),
    // ...
]);

// using registerProvider()
$expressionLanguage->registerProvider(new StringExpressionLanguageProvider());

Tip

ヒント

It is recommended to create your own ExpressionLanguage class in your library. Now you can add the extension by overriding the constructor:

ライブラリに独自の ExpressionLanguage クラスを作成することをお勧めします。これで、コンストラクターをオーバーライドして拡張機能を追加できます。
1
2
3
4
5
6
7
8
9
10
11
12
13
use Psr\Cache\CacheItemPoolInterface;
use Symfony\Component\ExpressionLanguage\ExpressionLanguage as BaseExpressionLanguage;

class ExpressionLanguage extends BaseExpressionLanguage
{
    public function __construct(CacheItemPoolInterface $cache = null, array $providers = [])
    {
        // prepends the default provider to let users override it
        array_unshift($providers, new StringExpressionLanguageProvider());

        parent::__construct($cache, $providers);
    }
}