跳到内容

表达式语法

编辑此页

ExpressionLanguage 组件 使用了一种特定的语法,该语法基于 Twig 的表达式语法。在本文档中,您可以找到所有支持的语法。

支持的字面量

该组件支持

  • 字符串 - 单引号和双引号 (例如 'hello')
  • 数字 - 整数 (例如 103),小数 (例如 9.95),不带前导零的小数 (例如 .99,等同于 0.99);所有数字都支持可选的下划线作为分隔符,以提高可读性 (例如 1_000_000, 3.14159_26535)
  • 数组 - 使用类似 JSON 的表示法 (例如 [1, 2])
  • 哈希 - 使用类似 JSON 的表示法 (例如 { foo: 'bar' })
  • 布尔值 - truefalse
  • null - null
  • 指数 - 也称为科学计数法 (例如 1.99E+31e-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

位运算符

  • & (与)
  • | (或)
  • ^ (异或)
  • ~ (非)
  • << (左移)
  • >> (右移)

7.2

Symfony 7.2 中引入了对 ~<<>> 位运算符的支持。

比较运算符

  • == (等于)
  • === (全等)
  • != (不等于)
  • !== (非全等)
  • < (小于)
  • > (大于)
  • <= (小于等于)
  • >= (大于等于)
  • 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

注意

innot 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.age1845 的范围内。

三元运算符

  • foo ? 'yes' : 'no'
  • foo ?: 'no' (等同于 foo ? foo : 'no')
  • foo ? 'yes' (等同于 foo ? 'yes' : '')

运算符优先级

运算符优先级决定了表达式中运算的处理顺序。例如,表达式 1 + 2 * 4 的结果是 9 而不是 12,因为乘法运算符 (*) 的优先级高于加法运算符 (+)。

为了避免歧义 (或更改操作的默认顺序),请在表达式中添加括号 (例如 (1 + 2) * 41 + (2 * 4)

下表总结了运算符及其结合性,从最高优先级到最低优先级

运算符 结合性
- , +, ~ (添加数字符号的一元运算符)
**
*, /, %
not, !
~
+, -
.., <<, >>
==, ===, !=, !==, <, >, >=, <=, not in, in, contains, starts with, ends with, matches
&
^
|
and, &&
xor
or, ||

内置对象和变量

当在 Symfony 应用程序内部使用此组件时,Symfony 会自动注入某些对象和变量,因此您可以在表达式中使用它们 (例如,请求、当前用户等)。

本作品,包括代码示例,根据 Creative Commons BY-SA 3.0 许可获得许可。
目录
    版本