运算符接收一个或多个值,并产生一个新值:$a + $b 做加法,$a . $b 连接字符串,$a && $b 是逻辑与,$a === $b 做比较,$i++ 做自增。
除非两个整数能整除,否则 / 返回浮点数:17 / 5 是 3.4,10 / 5 是整数 2。只想要整数部分时,使用 intdiv()。舍入的内容见数学函数页面。
算术运算符
| 运算符 | 名称 | 示例 | 结果 |
|---|---|---|---|
+ | 加法 | 7 + 2 | 9 |
- | 减法 | 7 - 2 | 5 |
* | 乘法 | 7 * 2 | 14 |
/ | 除法 | 7 / 2 | 3.5 |
% | 取模(余数) | 7 % 2 | 1 |
** | 幂 | 7 ** 2 | 49 |
-$a | 取反 | -7 | -7 |
取模适合用来处理“每隔 N 个元素”和判断奇偶。它的结果符号与左边的操作数相同,除以零会抛出一个可以捕获的错误:
赋值运算符
= 存储一个值。每个算术运算符和字符串运算符都有对应的组合形式,可以直接更新变量。
??= 属于 null 合并运算符一族。只有当变量未设置或为 null 时,它才会赋值。
自增和自减:++ 和 --
$i++ 先返回当前值,再加 1。++$i 先加 1,再返回新值。只有在同一个表达式中使用它的结果时,两者的区别才会显现。
很多程序就是用这个字母技巧来生成电子表格的列名(A、B …… Z、AA)。
逻辑运算符:&&、||、! 和 xor
| 运算符 | 何时为真 |
|---|---|
$a && $b | 两者都为真 |
$a || $b | 至少一个为真 |
!$a | $a 为假 |
$a xor $b | 恰好一个为真 |
$a and $b、$a or $b | 与 && 和 || 相同,但优先级更低 |
&& 和 || 会短路:当左边已经决定了结果时,右边不会被求值。正因如此,isset($user) && $user->isAdmin() 才是安全的。
and 与 &&:优先级陷阱
and 和 or 的结合力比 = 弱,所以在赋值语句中,它们在值被存储之后才生效。这是一个经典 bug:
低优先级只在一种惯用写法中有用:$file = fopen($path, 'r') or die('Cannot open');,这里你正是希望赋值先执行。其他地方一律使用 && 和 ||。
字符串运算符:. 和 .=
PHP 有两个字符串运算符:. 连接两个字符串("Grace" . " " . "Hopper"),.= 把内容追加到变量末尾($html .= "<li>")。+ 从不连接字符串:"3" + "4" 是数字 7,而 "3" . "4" 是字符串 "34"。插值和引号的用法见字符串页面。
比较运算符和太空船运算符 <=>
== 先转换类型再比较,=== 还会检查类型,<=> 返回 -1、0 或 1,这正是排序回调所需要的。详细说明和完整的松散比较表见比较运算符页面。
数组运算符
数组上的 + 是并集:左边数组的键优先,右边数组只补充左边缺少的键。以为它会追加元素的人常常会被吓一跳。== 检查键值对是否相同,=== 还要求顺序和类型都相同。
要把一个列表追加到另一个列表后面,使用 array_merge() 或展开语法 [...$a, ...$b]。
运算符优先级
当一个表达式混用多个运算符时,PHP 会按固定的顺序执行它们。下面是最容易出错的几种,以及 PHP 8.3 的输出:
echo 2 + 3 * 4; // 14: * before +
echo (2 + 3) * 4; // 20
echo 2 ** 3 ** 2; // 512: right to left, 2 ** 9
echo -2 ** 2; // -4: ** before unary minus
echo "Sum: " . 2 + 3; // Sum: 5, since PHP 8 + runs before .
拿不准时就加括号。括号没有任何代价,下一个读这行代码的人也不必去记优先级表。
常见问题
PHP 中 and 和 && 有什么区别?
两者都是逻辑与,但 and 的优先级比 = 低。所以 $x = true and false; 把 true 存进 $x(赋值先执行),而 $x = true && false; 存的是 false。在表达式中使用 && 和 ||,不要在赋值语句里用 and/or。
PHP 中 % 是做什么的?
% 是取模运算符:返回整数除法的余数,所以 10 % 3 是 1。结果的符号与左操作数相同(-7 % 3 是 -1)。浮点数请用 fmod(),而 % 0 会抛出 DivisionByZeroError。
PHP 中怎么计算一个数的几次方?
使用 ** 运算符:2 ** 10 是 1024。它是右结合的,所以 2 ** 3 ** 2 就是 2 ** 9 = 512;它的优先级也比一元负号高,所以 -2 ** 2 是 -4。函数 pow(2, 10) 的作用相同。
PHP 中 $i++ 和 ++$i 有什么区别?
两者都给 $i 加 1。$i++(后置自增)先返回旧值再加 1;++$i(前置自增)先加 1 再返回新值。单独写成一行时(比如 for 循环的步进部分),两者没有区别。