Расширение ExpressionLanguage
Расширение ExpressionLanguage
ExpressionLanguage может быть расширен путём добавление пользовательских функций. Например, в фреймворке Symfony, безопасность имеет настраиваемые функции для проверки роли пользователя.
Note
Если вы хотите узнать, как использовать функции в выражении, см. "".
Регистрация функций
Функции регистрируются в каждом конкретном экземпляре ExpressionLanguage.
Это означает, что функции могут быть использованы в любом выражении, выполняемом
этим экземпляром.
Для того, чтобы зарегистрировать функцию, используйте register(). Этот метод имеет 3 аргумента:
- name - Имя функции в выражении;
- compiler - Функция, выполняемая при компиляции выражения, использующего функцию;
- evaluator - Функция, выполняемая при оценке выражения.
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")'));
// это выведет: helloВ дополнение к пользовательским аргументам функции, evaluator передатся
переменная arguments в качестве первого аргумента, который эквивалентен
второму аргументу compile() (например, "значения" при оценке выражения).
Использование поставщиков выражений
Когда вы используете в вашей библиотеке класс ExpressionLanguage, вам
часто может хотеться добавить пользовательские функции. Чтобы сделать это,
вы можете создать новый поставщик выражений, создав класс, реализующий
ExpressionFunctionProviderInterface.
Этот интерфес требует одного метода: getFunctions(), который возвращает массив функций выражения (экземпляры ExpressionFunction) для регистрации:
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 array(
            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
Чтобы создать функцию выражения из PHP функции со статическим методом fromPhp():
1
ExpressionFunction::fromPhp('strtoupper');Функции с пространством имён поддерживаются, но они требуют второго аргумента для определения имени выражения:
1
ExpressionFunction::fromPhp('My\strtoupper', 'my_strtoupper');Вы можете зарегистрировать поставщика, используя registerProvider() или используя второй аргумент конструктора:
1 2 3 4 5 6 7 8 9 10
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
// использование конструктора
$expressionLanguage = new ExpressionLanguage(null, array(
    new StringExpressionLanguageProvider(),
    // ...
));
// использование registerProvider()
$expressionLanguage->registerProvider(new StringExpressionLanguageProvider());Tip
Рекомендуется создать ваш собственный класс 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 $parser = null, array $providers = array())
    {
        // добавляет к поставщику по умолчанию, чтобы позволить пользователем легко его переопределять
        array_unshift($providers, new StringExpressionLanguageProvider());
        parent::__construct($parser, $providers);
    }
}