七月
13
2016

扩展表达式语言

表达式语言可以通过添加自定义函数进行扩展。例如,在 Symfony 框架中,Security 实现了一个自定义函数用于检查用户角色。

如果想要了解如何在表达式中使用函数,可参考 使用函数 (英文

注册函数

函数会在每一个特定的 表达式语言 实例上进行注册。这意味着实例中这些被注册的函数可以被实例中的任意表达式执行。

要注册一个函数,需要使用 register() 方法。该方法有三个参数:

  • name - 函数在表达式中的名称
  • compiler - 编译表达式时要使用的函数
  • evaluator - 执行表达式时要使用的函数
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;

$language = new ExpressionLanguage();
$languate->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($language->evaluate('lowercase("HELLO")'));

以上程序会输出 hellocompilerevaluator 两个编译器都将 arguments 变量作为首个参数,该参数的性质等效于 evaluate()comple() 方法的第二个参数(例如:执行时传递的 values,编译时传递的 names)。

使用表达式供应器

当项目中使用 ExpressionLanguage 类时,你经常会需要添加自定义函数。因此,你可以通过实现 ExpressionFunctionProviderInterface 接口创建一个新的表达式供应器。

该接口必须实现一个方法:getFunctions(),该方法需要返回一个值为需要注册的表达式函数(ExpressionFunction 类的实例)数组。

use Symfony\Component\ExpressionLanguage\ExpressionFunction;
use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;

class StringExpressionLanuageProvider 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);
            }
        );
    }
}

你可以使用 registerProvider() 方法或者通过 ExpressionLanguage 类的构造方法的第二个参数来注册供给器:

use Symfony\Component\ExpressionLanguage\ExpressionLanguage;

// 通过构造器进行注册
$language = new ExpressionLanguage(null, array(
    new StringExpressionLanguageProvider(),
    // ...
));

// 通过 registerProvider() 方法注册
$language->registerProvider(new StringExpressionLanguageProvider());

推荐在项目中的创建自定义的 ExpressionLanguage 类。目前你可以通过重写构造器来添加扩展功能:

use Symfony\Component\ExpressionLanguage\ExpressionLanguage as BaseExpressionLanguage;
use Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheInterface;
class ExpressionLanguage extends BaseExpressionLanguage
{
  public function __construct(ParserCacheInterface $parser = null, array $providers = array())
  {
      // 预加载默认的供给器以便于用户进行重载
      array_unshift($provider, new StringExpressionLanguageProvider());
      parent::__construct($parser, $providers);
  }
}

原文地址:Extending the ExpressionLanguage

非特殊注明博文为 爱PHP吧(www.iphp8.com)原创内容,转载请注明原文地址:http://www.iphp8.com/?post=95

评论

发表评论:

(选填)

(选填)