扩展ExpressionLanguage类

3.4 版本
维护中的版本

ExpressionLanguage可能通过添加自定义函数来扩展。例如,在Symfony框架中,security就有自定义函数用来检查用户的角色(role)。

要了解在表达式中如何使用函数,参考使用函数小节。

注册函数 

函数会被注册到每一个特殊的 ExpressionLanguage 实例。这意味着函数可以被用在任何由该实例所执行的表达式中。

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

  • name - 表达式中的函数名称;
  • compiler - 当使用函数来编译表达式时,要被执行的函数;
  • evaluator - 当表达式被计算时,要被执行的函数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
 
$language = new ExpressionLanguage();
$language->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()compile() 方法的第二个参数(如,在evaluating时的"values",或是在compiling时的"names")。

使用表达式providers 

当你在自己的类库中使用 ExpressionLanguage 类时,你经常需要向它添加自定义函数。要实现这个,通过实现 ExpressionFunctionProviderInterface 接口来创建一个新的expression provider。

接口需要一个方法: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);
            }),
        );
    }
}

你可以使用 registerProvider() 方法来注册providers,或者使用构造器的第二个参数:

1
2
3
4
5
6
7
8
9
10
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
 
// using the constructor
$language = new ExpressionLanguage(null, array(
    new StringExpressionLanguageProvider(),
    // ...
));
 
// using registerProvider()
$language->registerProvider(new StringExpressionLanguageProvider());

推荐在你的类库中创建你自己的ExpressionLanguage类。现在你可以覆写构造器来添加扩展:

1
2
3
4
5
6
7
8
9
10
11
12
13
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())
    {
        // prepend the default provider to let users override it easily
        array_unshift($providers, new StringExpressionLanguageProvider());
 
        parent::__construct($parser, $providers);
    }
}

本文,包括例程代码在内,采用的是 Creative Commons BY-SA 3.0 创作共用授权。

登录symfonychina 发表评论或留下问题(我们会尽量回复)