PHP 运算符

Arithmetic, assignment, comparison, logic, bitwise, plus PHP-specific <=> and ??.

Beginner
Key Points`==` compares loosely, `===` compares type too, and `.` concatenates instead of adding.

算术运算符

PHP
<?php
echo 7 + 3, " ", 7 - 3, " ", 7 * 3, " ", 7 / 2, " ", 7 % 3, "\n";
echo intdiv(7, 2), " ", 2 ** 10, "\n";

// 取模结果符号跟被除数走
echo -7 % 3, " ", 7 % -3, "\n";

// 字符串拼接
echo "a" . 1 . 2, "\n";
Output
10 4 21 3.5 1
3 1024
-1 1
a12
7 / 2 yields 3.5. PHP's / returns int when evenly divisible, float otherwise. Use intdiv() for integer division; casting rounds toward zero.

赋值运算符

PHP
<?php
$x = 10;
$x += 5;   echo $x, "\n";   // 15
$x -= 3;   echo $x, "\n";   // 12
$x *= 2;   echo $x, "\n";   // 24
$x /= 4;   echo $x, "\n";   // 6
$x %= 4;   echo $x, "\n";   // 2
$x **= 3;  echo $x, "\n";   // 8

$s = "a";
$s .= "b";
$s .= "c";
echo $s, "\n";              // abc

$arr = [1];
$arr[] = 2;
$arr[] = 3;
echo implode(",", $arr), "\n";
Output
15
12
24
6
2
8
abc
1,2,3

比较运算符

OperatorNameExampleResult
==等于(松散)10 == "10"true
===全等10 === "10"false
!=不等10 != "10"false
<>不等(旧写法)10 <> 11true
<=>飞船(三向比较)1 <=> 2-1
??空合并null ?? "x"x
PHP
<?php
var_dump(7 <=> 3, 3 <=> 3, 3 <=> 7);

// 空合并:左边为 null 或未定义时取右边
$name = null;
echo $name ?? "默认名", "\n";

// Elvis:左边为假值时取右边("" 0 "0" null [] 都算假)
echo "" ?: "空字符串", "\n";
echo "0" ?: "零", "\n";
Output
int(1)
int(0)
int(-1)
默认名
空字符串
零
"0" 是假值,所以 "0" ?: "零" 返回 "零"。这是 PHP 最反直觉的一条:非空字符串居然为假。判断「用户填了没有」不能用 ?:,要用 !== '' 或 isset()。

逻辑运算符

PHP
<?php
$a = true;
$b = false;

var_dump($a && $b);
var_dump($a || $b);
var_dump(!$a);
var_dump($a and $b);   // 优先级低于 =
var_dump($a xor $b);

// 短路
function sideEffect() {
    echo "被调用了\n";
    return true;
}
var_dump(false && sideEffect());
var_dump(true || sideEffect());
Output
bool(false)
bool(true)
bool(false)
bool(false)
bool(true)
bool(false)
bool(true)

&& and and differ in precedence: = binds tighter than and, so $x = true and false assigns true to $x. Always use && / ||.

位运算符

PHP
<?php
echo 6 & 3, "\n";    // 110 & 011 = 010
echo 6 | 3, "\n";    // 110 | 011 = 111
echo 6 ^ 3, "\n";    // 110 ^ 011 = 101
echo ~6, "\n";       // 取反
echo 1 << 4, "\n";   // 左移 = 乘 2^4
echo 256 >> 4, "\n"; // 右移 = 除 2^4
Output
2
7
5
-7
16
16

The classic use is permission bits: 1 << n for permission n, & to test, | to grant, ^ to revoke.

PHP
<?php
const READ    = 1 << 0;  // 1
const WRITE   = 1 << 1;  // 2
const EXECUTE = 1 << 2;  // 4

$perm = READ | EXECUTE;
echo $perm, "\n";                       // 5

var_dump((bool)($perm & READ));         // true
var_dump((bool)($perm & WRITE));        // false

$perm |= WRITE;
echo $perm, "\n";                       // 7

$perm &= ~EXECUTE;
echo $perm, "\n";                       // 3
Output
5
bool(true)
bool(false)
7
3

运算符优先级

No need to memorise the whole table — just the dangerous ones.

  1. . has the same precedence as + - — 1 . 2 + 3 is (1 . 2) + 3
  2. ! binds tighter than && but looser than ==
  3. and or xor bind looser than =
  4. ?? is right-associative
When unsure, add parentheses. They cost nothing; a precedence bug costs hours.

Friends & Partners