表达式语法
ExpressionLanguage 组件 使用了一种特定的语法,该语法基于 Twig 的表达式语法。在本文档中,您可以找到所有支持的语法。
支持的字面量
该组件支持
- 字符串 - 单引号和双引号 (例如
'hello'
) - 数字 - 整数 (例如
103
),小数 (例如9.95
),不带前导零的小数 (例如.99
,等同于0.99
);所有数字都支持可选的下划线作为分隔符,以提高可读性 (例如1_000_000
,3.14159_26535
) - 数组 - 使用类似 JSON 的表示法 (例如
[1, 2]
) - 哈希 - 使用类似 JSON 的表示法 (例如
{ foo: 'bar' }
) - 布尔值 -
true
和false
- null -
null
- 指数 - 也称为科学计数法 (例如
1.99E+3
或1e-2
) - 注释 - 使用
/*
和*/
(例如/* this is a comment */
)
7.2
Symfony 7.2 中引入了对表达式内注释的支持。
警告
反斜杠 (\
) 在字符串中必须用 3 个反斜杠 (
) 转义,在正则表达式中必须用 7 个反斜杠 (
) 转义
1 2
echo $expressionLanguage->evaluate('"\\\\"'); // prints \
$expressionLanguage->evaluate('"a\\\\b" matches "/^a\\\\\\\\b$/"'); // returns true
表达式中的控制字符 (例如 \n
) 将被空格替换。为了避免这种情况,请使用单个反斜杠转义序列 (例如 \\n
)。
使用对象
当将对象传递到表达式中时,您可以使用不同的语法来访问对象的属性和调用方法。
访问公共属性
可以使用 .
语法访问对象的公共属性,类似于 JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14
class Apple
{
public string $variety;
}
$apple = new Apple();
$apple->variety = 'Honeycrisp';
var_dump($expressionLanguage->evaluate(
'fruit.variety',
[
'fruit' => $apple,
]
));
这将打印出 Honeycrisp
。
调用方法
.
语法也可以用于调用对象的方法,类似于 JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
class Robot
{
public function sayHi(int $times): string
{
$greetings = [];
for ($i = 0; $i < $times; $i++) {
$greetings[] = 'Hi';
}
return implode(' ', $greetings).'!';
}
}
$robot = new Robot();
var_dump($expressionLanguage->evaluate(
'robot.sayHi(3)',
[
'robot' => $robot,
]
));
这将打印出 Hi Hi Hi!
。
空值安全运算符
使用 ?.
语法来访问可能是 null
的对象的属性和方法 (这等效于 PHP 空值安全运算符 $object?->propertyOrMethod
)
1 2 3 4 5 6 7
// these will throw an exception when `fruit` is `null`
$expressionLanguage->evaluate('fruit.color', ['fruit' => '...'])
$expressionLanguage->evaluate('fruit.getStock()', ['fruit' => '...'])
// these will return `null` if `fruit` is `null`
$expressionLanguage->evaluate('fruit?.color', ['fruit' => '...'])
$expressionLanguage->evaluate('fruit?.getStock()', ['fruit' => '...'])
空值合并运算符
如果左侧存在且不为 null
,则返回左侧;否则返回右侧。表达式可以链式使用多个合并运算符
foo ?? 'no'
foo.baz ?? 'no'
foo[3] ?? 'no'
foo.baz ?? foo['baz'] ?? 'no'
7.2
从 Symfony 7.2 开始,尝试访问不存在的变量时不会抛出异常。这与 PHP 中的空值合并运算符 的行为相同。
使用函数
您还可以通过使用与 PHP 和 JavaScript 相同的语法在表达式中使用注册的函数。ExpressionLanguage 组件默认带有以下函数
constant()
enum()
min()
max()
constant()
函数
此函数将返回 PHP 常量的值
1 2 3 4 5
define('DB_USER', 'root');
var_dump($expressionLanguage->evaluate(
'constant("DB_USER")'
));
这将打印出 root
。
这也适用于类常量
1 2 3 4 5 6 7 8 9 10
namespace App\SomeNamespace;
class Foo
{
public const API_ENDPOINT = '/api';
}
var_dump($expressionLanguage->evaluate(
'constant("App\\\SomeNamespace\\\Foo::API_ENDPOINT")'
));
这将打印出 /api
。
enum()
函数
此函数将返回枚举的 case
1 2 3 4 5 6 7 8 9 10
namespace App\SomeNamespace;
enum Foo
{
case Bar;
}
var_dump(App\Enum\Foo::Bar === $expressionLanguage->evaluate(
'enum("App\\\SomeNamespace\\\Foo::Bar")'
));
这将打印出 true
。
min()
函数
此函数将返回给定参数的最小值。您可以传递不同类型的参数 (例如,日期、字符串、数值),甚至可以混合它们 (例如,传递数值和字符串)。它在内部使用 min PHP 函数来查找最小值
1 2 3
var_dump($expressionLanguage->evaluate(
'min(1, 2, 3)'
));
这将打印出 1
。
max()
函数
此函数将返回给定参数的最大值。您可以传递不同类型的参数 (例如,日期、字符串、数值),甚至可以混合它们 (例如,传递数值和字符串)。它在内部使用 max PHP 函数来查找最大值
1 2 3
var_dump($expressionLanguage->evaluate(
'max(1, 2, 3)'
));
这将打印出 3
。
7.1
min()
和 max()
函数是在 Symfony 7.1 中引入的。
提示
要了解如何注册您自己的函数以在表达式中使用,请参阅 "ExpressionLanguage 组件"。
使用数组
如果将数组传递到表达式中,请使用 []
语法来访问数组键,类似于 JavaScript
1 2 3 4 5 6 7 8
$data = ['life' => 10, 'universe' => 10, 'everything' => 22];
var_dump($expressionLanguage->evaluate(
'data["life"] + data["universe"] + data["everything"]',
[
'data' => $data,
]
));
这将打印出 42
。
支持的运算符
该组件附带了许多运算符
算术运算符
+
(加法)-
(减法)*
(乘法)/
(除法)%
(取模)**
(幂)
例如
1 2 3 4 5 6 7 8
var_dump($expressionLanguage->evaluate(
'life + universe + everything',
[
'life' => 10,
'universe' => 10,
'everything' => 22,
]
));
这将打印出 42
。
比较运算符
==
(等于)===
(全等)!=
(不等于)!==
(非全等)<
(小于)>
(大于)<=
(小于等于)>=
(大于等于)matches
(正则表达式匹配)包含
以...开头
以...结尾
提示
要测试字符串是否不匹配正则表达式,请将逻辑 not
运算符与 matches
运算符结合使用
1
$expressionLanguage->evaluate('not ("foo" matches "/bar/")'); // returns true
您必须使用括号,因为一元运算符 not
的优先级高于二元运算符 matches
。
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
$ret1 = $expressionLanguage->evaluate(
'life == everything',
[
'life' => 10,
'everything' => 22,
]
);
$ret2 = $expressionLanguage->evaluate(
'life > everything',
[
'life' => 10,
'everything' => 22,
]
);
两个变量都将被设置为 false
。
逻辑运算符
not
或!
and
或&&
or
或||
xor
7.2
Symfony 7.2 中引入了对 xor
逻辑运算符的支持。
例如
1 2 3 4 5 6 7 8
$ret = $expressionLanguage->evaluate(
'life < universe or life < everything',
[
'life' => 10,
'universe' => 10,
'everything' => 22,
]
);
此 $ret
变量将被设置为 true
。
字符串运算符
~
(连接)
例如
1 2 3 4 5 6 7
var_dump($expressionLanguage->evaluate(
'firstName~" "~lastName',
[
'firstName' => 'Arthur',
'lastName' => 'Dent',
]
));
这将打印出 Arthur Dent
。
数组运算符
in
(包含)not in
(不包含)
这些运算符使用严格比较。例如
1 2 3 4 5 6 7 8 9 10 11 12 13 14
class User
{
public string $group;
}
$user = new User();
$user->group = 'human_resources';
$inGroup = $expressionLanguage->evaluate(
'user.group in ["human_resources", "marketing"]',
[
'user' => $user,
]
);
$inGroup
将评估为 true
。
注意
in
和 not in
运算符使用严格比较。
数值运算符
..
(范围)
例如
1 2 3 4 5 6 7 8 9 10 11 12 13 14
class User
{
public int $age;
}
$user = new User();
$user->age = 34;
$expressionLanguage->evaluate(
'user.age in 18..45',
[
'user' => $user,
]
);
这将评估为 true
,因为 user.age
在 18
到 45
的范围内。
三元运算符
foo ? 'yes' : 'no'
foo ?: 'no'
(等同于foo ? foo : 'no'
)foo ? 'yes'
(等同于foo ? 'yes' : ''
)
运算符优先级
运算符优先级决定了表达式中运算的处理顺序。例如,表达式 1 + 2 * 4
的结果是 9
而不是 12
,因为乘法运算符 (*
) 的优先级高于加法运算符 (+
)。
为了避免歧义 (或更改操作的默认顺序),请在表达式中添加括号 (例如 (1 + 2) * 4
或 1 + (2 * 4)
。
下表总结了运算符及其结合性,从最高优先级到最低优先级
运算符 | 结合性 |
---|---|
- , + , ~ (添加数字符号的一元运算符) |
无 |
** |
右 |
* , / , % |
左 |
not , ! |
无 |
~ |
左 |
+ , - |
左 |
.. , << , >> |
左 |
== , === , != , !== , < , > , >= , <= , not in , in , contains , starts with , ends with , matches |
左 |
& |
左 |
^ |
左 |
| |
左 |
and , && |
左 |
xor |
左 |
or , || |
左 |
内置对象和变量
当在 Symfony 应用程序内部使用此组件时,Symfony 会自动注入某些对象和变量,因此您可以在表达式中使用它们 (例如,请求、当前用户等)。