表达语言组件
编辑本页警告:您正在浏览的文档欧宝官网下载appob娱乐下载Symfony 6.0,现已不再维护。
读本页的更新版本用于Syob娱乐下载mfony 6.2(当前稳定版本)。
表达语言组件
ExpressionLanguage组件提供了一个可以编译和计算表达式的引擎。表达式是返回值的一行代码(主要是布尔值,但不限于此)。
安装
1
$作曲家需要交响乐/表达语言ob娱乐下载
请注意
如果在Symfony应用程序外部安装此组件,则必须要求ob娱乐下载供应商/ autoload.php
文件,以启用Composer提供的类自动加载机制。读这篇文章欲知详情。
表达式引擎如何帮助我?
该组件的目的是允许用户在配置中使用表达式来处理更复杂的逻辑。例如,Symfony框架在安全性、验证规则和路ob娱乐下载由匹配中使用了表达式。
除了在框架本身中使用该组件外,ExpressionLanguage组件是一个完美的候选组件业务规则引擎.这个想法是让网站管理员在不使用PHP和不引入安全问题的情况下,以动态的方式配置内容:
1 2 3 4 5 6 7 8
#当article. commentcount > 100和article. getgroup()在['good_customers', 'collaborator']中获得特价类别不在["misc"] #当产品。存量< 15
表达式可以被视为一个非常受限的PHP沙盒,不受外部注入的影响,因为必须显式地声明表达式中哪些变量可用。
使用
ExpressionLanguage组件可以编译和求值表达式。表达式是一行程序,通常返回布尔值,可由在类中执行表达式的代码使用如果
声明。表达式的一个简单例子是1 + 2
.您还可以使用更复杂的表达式,例如someArray [3] .someMethod(酒吧)
.
该组件提供了两种处理表达式的方法:
- 评价:表达式被求值而不被编译成PHP;
- 编译:表达式被编译成PHP,因此它可以被缓存和求值。
组件的主类是ExpressionLanguage:
1 2 3 4 5 6 7
使用ob娱乐下载\组件\ExpressionLanguage\ExpressionLanguage;$expressionLanguage=新ExpressionLanguage ();var_dump ($expressionLanguage->评估(“1 + 2”));//显示3var_dump ($expressionLanguage->编译(“1 + 2”));//显示(1 + 2)
表达式语法
ExpressionLanguage组件使用了基于Twig的表达式语法的特定语法。在本文档中,您可以找到所有受支持的语法。
支持文字
该组件支持:
- 字符串-单引号和双引号(例如:
“你好”
) - 数字——如。
103
- 数组-使用类似json的符号(例如:
[1,2]
) - 散列-使用类似json的符号(例如:
{foo: 'bar'}
) - 布尔值-
真正的
而且假
- 零-
零
- 指数-也被称为科学的(例如:
1.99 e + 3
或1)依照
)
谨慎
反斜杠(\
)必须用4个反斜杠(
)和8个反斜杠(
)的正则表达式:
1 2
回声$expressionLanguage->评估(’“\ \ \ \”);//打印\$expressionLanguage->评估(' ' a\\\\b ' '匹配' /^a\\\\\\\\b$/ ' ');//返回true
控制字符(例如:\ n
)中的表达式被替换为空格。为了避免这种情况,使用一个反斜杠转义序列(例如。\ \ n
).
使用对象
将对象传递到表达式时,可以使用不同的语法来访问对象的属性和调用方法。
进入公共物业
对象上的公共属性可以使用.
语法,类似于JavaScript:
12 3 4 5 6 7 8 9 10 11 12 13 14
类苹果{公共$各种;}$苹果=新苹果();$苹果->各种=“密脆”;var_dump ($expressionLanguage->评估(“fruit.variety”, (“水果”= >$苹果,]));
这会打印出来密脆
.
调用方法
的.
语法也可以用来调用一个对象的方法,类似于JavaScript:
12 3 4 5 6 7 8 9 10 11 12 13 14 16 17 18 19 20 21
类机器人{公共函数sayHi($次){$问候= [];为($我=0;$我<$次;$我+ +) {$问候[] =“嗨”;}返回内爆(' ',$问候).“!”;}}$机器人=新机器人();var_dump ($expressionLanguage->评估(“robot.sayHi(3)”, (“机器人”= >$机器人,]));
这会打印出来嗨嗨嗨!
.
使用函数
还可以使用与PHP和JavaScript相同的语法在表达式中使用注册函数。ExpressionLanguage组件默认带有一个函数:常数()
,它将返回PHP常量的值:
1 2 3 4 5
定义(“DB_USER”,“根”);var_dump ($expressionLanguage->评估(“常数(“DB_USER”)”));
这会打印出来根
.
提示
若要阅读如何注册要在表达式中使用的自己的函数,请参阅“表达语言组件".
使用数组
如果将数组传递给表达式,请使用[]
语法来访问数组键,类似于JavaScript:
1 2 3 4 5 6 7 8
$数据= (“生活”= >10,“宇宙”= >10,“一切”= >22];var_dump ($expressionLanguage->评估(data[“生命”]+ data[“宇宙”]+ data[“一切”], (“数据”= >$数据,]));
这会打印出来42
.
支持运营商
该组件带有很多操作符:
算术运算符
+
(添加)-
(减法)*
(乘法)/
(部门)%
(模量)**
(战俘)
例如:
1 2 3 4 5 6 7 8
var_dump ($expressionLanguage->评估(“生命+宇宙+一切”, (“生活”= >10,“宇宙”= >10,“一切”= >22,]));
这会打印出来42
.
按位运算符
&
(和)|
(或)^
(xor)
比较运算符
==
(等于)===
(相同)! =
(不等于)= = !
(不一样的)<
(小于)>
(大于)< =
(小于或等于)> =
(大于等于)匹配
(正则表达式匹配)
提示
来测试字符串是否存在不匹配正则表达式,使用逻辑不
运算符与匹配
接线员:
1
$expressionLanguage->评估('not ("foo"匹配"/bar/")');//返回true
必须使用圆括号,因为一元操作符不
优先于二进制操作符匹配
.
例子:
12 3 4 5 6 7 8 9 10 11 12 13 14 15
$ret1=$expressionLanguage->评估(“生命=一切”, (“生活”= >10,“一切”= >22,]);$ret2=$expressionLanguage->评估(“生活>一切”, (“生活”= >10,“一切”= >22,]);
两个变量都被设为假
.
逻辑运算符
不
或!
而且
或& &
或
或||
例如:
1 2 3 4 5 6 7 8
$受潮湿腐烂=$expressionLanguage->评估(生命<宇宙或生命<一切, (“生活”= >10,“宇宙”= >10,“一切”= >22,]);
这美元受潮湿腐烂
变量将被设置为真正的
.
字符串运算符
~
(连接)
例如:
1 2 3 4 5 6 7
var_dump ($expressionLanguage->评估(“姓~ " ~名”, (“firstName”= >“亚瑟”,“姓”= >“削弱”,]));
这会打印出来亚瑟削弱
.
数组运算符
在
(包含)不是在
(不包含)
例如:
12 3 4 5 6 7 8 9 10 11 12 13 14
类用户{公共$集团;}$用户=新用户();$用户->组=“human_resources”;$派系=$expressionLanguage->评估(的用户。集团在["human_resources", "marketing"]', (“用户”= >$用户,]);
的美元的派系
会计算为真正的
.
数字运算符
..
(范围)
例如:
12 3 4 5 6 7 8 9 10 11 12 13 14
类用户{公共$年龄;}$用户=新用户();$用户->年龄=34;$expressionLanguage->评估(的用户。年龄在18..45', (“用户”= >$用户,]);
它的值是真正的
,因为user.age
在范围内18
来45
.
三元运算符
foo吗?“是”:“不是”
Foo ?: 'no'
(等于foo吗?Foo:“不”
)foo吗?“是的”
(等于foo吗?“是的”。
)
传入变量
你也可以将变量传递到表达式中,它可以是任何有效的PHP类型(包括对象):
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
使用ob娱乐下载\组件\ExpressionLanguage\ExpressionLanguage;$expressionLanguage=新ExpressionLanguage ();类苹果{公共$各种;}$苹果=新苹果();$苹果->各种=“密脆”;var_dump ($expressionLanguage->评估(“fruit.variety”, (“水果”= >$苹果,]));//显示"Honeycrisp"
当在Symfony应用程序中使用这个组件时,某些对象和变量会被Symfob娱乐下载ony自动注入,这样你就可以在你的表达式中使用它们(例如请求,当前用户等):
谨慎
在表达式中使用变量时,避免将不可信的数据传递到变量数组中。如果无法避免这种情况,请清除不受信任数据中的非字母数字字符,以防止恶意用户注入控制字符并更改表达式。
缓存
ExpressionLanguage组件提供了一个编译()方法,以便能够在纯PHP中缓存表达式。但是在内部,组件还缓存解析过的表达式,因此可以更快地编译/求值重复的表达式。
工作流
这两个evaluate ()而且编译()
需要做一些事情才能提供各自的返回值。为evaluate ()
,这个开销更大。
这两种方法都需要对表达式进行标记化和解析。这是由parse ()方法。它返回一个ParsedExpression.现在,编译()
方法只返回此对象的字符串转换。的evaluate ()
方法需要遍历“节点”(保存在ParsedExpression
),并对他们进行评估。
为了节省时间ExpressionLanguage
缓存ParsedExpression
因此,它可以跳过带有重复表达式的标记化和解析步骤。缓存是由PSR-6完成的CacheItemPoolInterface实例(默认情况下,它使用ArrayAdapter).你可以通过创建一个自定义缓存池或使用一个可用的缓存池并使用构造函数注入缓存池来自定义缓存池:
1 2 3 4 5
使用ob娱乐下载\组件\缓存\适配器\RedisAdapter;使用ob娱乐下载\组件\ExpressionLanguage\ExpressionLanguage;$缓存=新RedisAdapter(…);$expressionLanguage=新ExpressionLanguage ($缓存);
另请参阅
看到缓存组件欧宝官网下载app有关可用缓存适配器的更多信息的文档。
使用解析表达式和序列化表达式
这两个evaluate ()
而且编译()
可以处理ParsedExpression
而且SerializedParsedExpression
:
1 2 3 4 5 6
/ /……// parse()方法返回一个ParsedExpression$表达式=$expressionLanguage->解析(“1 + 4”[]);var_dump ($expressionLanguage->评估($表达式));//打印5个
1 2 3 4 5 6 7 8 9
使用ob娱乐下载\组件\ExpressionLanguage\SerializedParsedExpression;/ /……$表达式=新SerializedParsedExpression (“1 + 4”序列化($expressionLanguage->解析(“1 + 4”[])->getNodes ()));var_dump ($expressionLanguage->评估($表达式));//打印5个
AST转储和编辑
很难操作或检查用ExpressionLanguage组件创建的表达式,因为表达式是普通字符串。更好的方法是将这些表达式转换为AST。在计算机科学中,AST(抽象语法树)是用编程语言编写的源代码结构的树形表示.在Syob娱乐下载mfony中,ExpressionLanguage AST是一组节点,其中包含表示给定表达式的PHP类。
丢弃AST
调用getNodes ()方法来解析任何表达式以获取其AST:
12 3 4 5 6 7 8 9 10 11 12
使用ob娱乐下载\组件\ExpressionLanguage\ExpressionLanguage;$ast= (新ExpressionLanguage ())->解析(“1 + 2”[])->getNodes ();// dump AST节点进行检查var_dump ($ast);//将AST节点转储为字符串表示形式$astAsString=$ast->dump ();
操作AST
还可以将AST的节点转储到PHP节点数组中,以便对它们进行操作。调用toArray ()方法将AST转换为数组:
1 2 3 4 5 6 7
/ /……$astAsArray= (新ExpressionLanguage ())->解析(“1 + 2”[])->getNodes ()->toArray ();
扩展表达语言
可以通过添加自定义函数来扩展ExpressionLanguage。例如,在Symfony框架中,安全性具有检ob娱乐下载查用户角色的自定义函数。
请注意
如果您想了解如何在表达式中使用函数,请阅读“表达语言组件".
注册功能
函数被注册在每个特定的函数上ExpressionLanguage
实例。这意味着函数可以在该实例执行的任何表达式中使用。
要注册一个函数,使用注册().这个方法有3个参数:
- 的名字-表达式中函数的名称;
- 编译器-在使用该函数编译表达式时执行的函数;
- 评估者—表达式求值时执行的函数。
例子:
12 3 4 5 6 7 8 9 10 11 12 13 14 15
使用ob娱乐下载\组件\ExpressionLanguage\ExpressionLanguage;$expressionLanguage=新ExpressionLanguage ();$expressionLanguage->注册(“小写”,函数($str){返回sprintf (”(is_string (% 1 $ s) ?strotolower (%1$s): %1$s)',$str);},函数($参数,$str){如果(!我s_string($str)) {返回$str;}返回函数$str);});var_dump ($expressionLanguage->评估(“小写(“HELLO”)”));//这将打印:hello
除了自定义函数参数外,评估者传递一个参数
变量作为它的第一个参数,它等于的第二个参数evaluate ()
(例如,求值表达式时的“值”)。
使用表达式提供程序
当你使用ExpressionLanguage
类时,通常希望添加自定义函数。为此,可以通过创建实现的类来创建新的表达式提供程序ExpressionFunctionProviderInterface.
该接口需要一个方法:getFunctions ()的实例,返回表达式函数的数组ExpressionFunction)登记:
12 3 4 5 6 7 8 9 10 11 12 13 14 16 17 18 19 20
使用ob娱乐下载\组件\ExpressionLanguage\ExpressionFunction;使用ob娱乐下载\组件\ExpressionLanguage\ExpressionFunctionProviderInterface;类StringExpressionLanguageProvider实现了ExpressionFunctionProviderInterface{公共函数getFunctions(){返回[新ExpressionFunction (“小写”,函数($str){返回sprintf (”(is_string (% 1 $ s) ?strotolower (%1$s): %1$s)',$str);},函数($参数,$str){如果(!我s_string($str)) {返回$str;}返回函数$str);}));}}
提示
方法从PHP函数创建表达式函数fromPhp ()静态方法:
1
ExpressionFunction::fromPhp (“strtoupper”);
支持命名空间函数,但它们需要第二个参数来定义表达式的名称:
1
ExpressionFunction::fromPhp (“我的\ strtoupper”,“my_strtoupper”);
您可以使用registerProvider ()或者使用构造函数的第二个参数:
1 2 3 4 5 6 7 8 9 10
使用ob娱乐下载\组件\ExpressionLanguage\ExpressionLanguage;//使用构造函数$expressionLanguage=新ExpressionLanguage (零, (新StringExpressionLanguageProvider (),/ /……]);//使用registerProvider()$expressionLanguage->registerProvider (新StringExpressionLanguageProvider ());
提示
建议您自己创建ExpressionLanguage
在你的图书馆上课。现在你可以通过重写构造函数来添加扩展:
12 3 4 5 6 7 8 9 10 11 12 13
使用Psr\缓存\CacheItemPoolInterface;使用ob娱乐下载\组件\ExpressionLanguage\ExpressionLanguage作为BaseExpressionLanguage;类ExpressionLanguage扩展BaseExpressionLanguage{公共函数__construct(CacheItemPoolInterface$缓存= null,数组$供应商= []){//将默认提供程序放在前面,让用户重写它函数$供应商,新StringExpressionLanguageProvider ());父::__construct ($缓存,$供应商);}}