运算符优先级

运算符优先级指定了两个表达式绑定得有多"紧密"。例如,表达式 1 + 5 * 3 的结果是 16 而不是 18 是因为乘号("*")的优先级比加号("+")高。必要时可以用括号来强制改变优先级。例如:(1 + 5) * 3 的值为 18

如果运算符优先级相同,那运算符的结合方向决定了该如何运算。例如,"-"是左联的,那么 1 - 2 - 3 就等同于 (1 - 2) - 3 并且结果是 -4. 另外一方面,"="是右联的,所以 $a = $b = $c 等同于 $a = ($b = $c)

没有结合的相同优先级的运算符不能连在一起使用,例如 1 < 2 > 1 在PHP是不合法的。但另外一方面表达式 1 <= 1 == 1 是合法的, 因为 == 的优先级低于 <=

括号的使用,哪怕在不是必要的场合下,通过括号的配对来明确标明运算顺序,而非靠运算符优先级和结合性来决定,通常能够增加代码的可读性。

下表按照优先级从高到低列出了运算符。同一行中的运算符具有相同优先级,此时它们的结合方向决定求值顺序。

运算符优先级
结合方向 运算符 附加信息
不适用 clone new clonenew
** 算术运算符
不适用 ++ -- ~ (int) (float) (string) (array) (object) (bool) @ 类型递增/递减
instanceof 类型
不适用 ! 逻辑运算符
* / % 算术运算符
+ - . 算术运算符字符串运算符
<< >> 位运算符
< <= > >= 比较运算符
== != === !== <> <=> 比较运算符
& 位运算符引用
^ 位运算符
| 位运算符
&& 逻辑运算符
|| 逻辑运算符
?? null 合并运算符
? : 三元运算符
= += -= *= **= /= .= %= &= |= ^= <<= >>= ??= 赋值运算符
不适用 yield from yield from
不适用 yield yield
不适用 print print
and 逻辑运算符
xor 逻辑运算符
or 逻辑运算符

Example #1 结合方向

<?php
$a 
5// (3 * 3) % 5 = 4
// ternary operator associativity differs from C/C++
$a true true 2// (true ? 0 : true) ? 1 : 2 = 2

$a 1;
$b 2;
$a $b += 3// $a = ($b += 3) -> $a = 5, $b = 5
?>

Operator precedence and associativity only determine how expressions are grouped, they do not specify an order of evaluation. PHP does not (in the general case) specify in which order an expression is evaluated and code that assumes a specific order of evaluation should be avoided, because the behavior can change between versions of PHP or depending on the surrounding code.

Example #2 Undefined order of evaluation

<?php
$a 
1;
echo 
$a $a++; // may print either 2 or 3

$i 1;
$array[$i] = $i++; // may set either index 1 or 2
?>

Example #3 +-. 具有相同的优先级

<?php
$x 
4;
// this line might result in unexpected output:
echo "x minus one equals " $x-", or so I hope\n";
// because it is evaluated like this line:
echo (("x minus one equals " $x) - 1) . ", or so I hope\n";
// the desired precedence can be enforced by using parentheses:
echo "x minus one equals " . ($x-1) . ", or so I hope\n";
?>

以上例程会输出:

-1, or so I hope
-1, or so I hope
x minus one equals 3, or so I hope

Note:

尽管 = 比其它大多数的运算符的优先级低,PHP 仍旧允许类似如下的表达式:if (!$a = foo()),在此例中 foo() 的返回值被赋给了 $a

User Contributed Notes

instatiendaweb at gmail dot com 20-Feb-2021 09:44
//incorrect
$a = true ? 0 : true ? 1 : 2; // (true ? 0 : true) ? 1 : 2 = 2
//Unparenthesized `a ? b : c ? d : e` is not supported. Use either `(a ? b : c) ? d : e` or `a ? b : (c ? d : e)`
//correct
$a = (true ? 0 : true) ? 1 : 2; // (true ? 0 : true) ? 1 : 2 = 2

==> correction documentation.
anisgazig at gmail dot com 01-Feb-2021 03:36
Three types of operator associativity in php.
1.left
2.rigt
3.non-associativity

Category of three operators are right associativity
1)**
2)=,+=,-=,*=,/=,%=,&=,^=,|=,<<=,>>=,??=,.=
3)??

Category of eight operators are non-associativity
1)clone new
2)++,--,~,@
3)!
4)<,<=,>,>=
5)<<,>>
6)yield from
7)yield
8)print

Rest of the operators are left associativity
noone 23-Feb-2020 02:46
Something that threw me of guard and I hadn't found it mentioned anywhere is if you're looking to asign a value in an if statement condition and use the same value in the said condition and compare it to a different value note the precedence of operators.

if($a=5&&$a==5){
  echo '5';
} else {
  echo 'not 5';
}
//echos  not 5

You'll get a Notice:  Undefined variable: a;
This happens because the expression is treated as
($a=5&&($a==5))
In this case $a was undefined.

Use parentheses to enforce the desired outcome or and instead of &&.
if(($a=5)&&$a==5){ // or $a=5 and $a==5
  echo '5';
} else {
  echo 'not 5';
}

//echos  5

We get no notice!

A use case for this can be a three part condition that first checks if a value is valid, second assigns a new variable based on the first value and then checks if the result is valid.

$ID=100;

if ($ID&&($data=get_table_row_for_ID($ID))&&$data->is_valid()) { //NOTE: assigned $data
 // do something with the data
}

If assigning variables in an if condition I recommend adding a comment at the end of the line that such an action took place.
aaronw at catalyst dot net dot nz 11-Aug-2017 01:18
If you've come here looking for a full list of PHP operators, take note that the table here is *not* complete. There are some additional operators (or operator-ish punctuation tokens) that are not included here, such as "->", "::", and "...".

For a really comprehensive list, take a look at the "List of Parser Tokens" page: http://php.net/manual/en/tokens.php
ivan at dilber dot info 24-Apr-2017 03:55
<?php
// Another tricky thing here is using && or || with ternary ?:
$x && $y ? $a : $b// ($x && $y) ? $a : $b;

// while:
$x and $y ? $a : $b// $x and ($y ? $a : $b);

?>
karlisd at gmail dot com 10-Nov-2015 05:39
Sometimes it's easier to understand things in your own examples.
If you want to play around operator precedence and look which tests will be made, you can play around with this:

<?php
function F($v) {echo $v." "; return false;}
function
T($v) {echo $v." "; return true;}

IF (
F(0) || T(1) && F(2)  || F(3)  && ! F(4) ) {
  echo
"true";
} else echo
" false";
?>
Now put in IF arguments f for false and t for true, put in them some ID's. Play out by changing "F" to "T" and vice versa, by keeping your ID the same. See output and you will know which arguments  actualy were checked.
fabmlk 02-Jun-2015 05:41
Watch out for the difference of priority between 'and vs &&' or '|| vs or':
<?php
$bool
= true && false;
var_dump($bool); // false, that's expected

$bool = true and false;
var_dump($bool); // true, ouch!
?>
Because 'and/or' have lower priority than '=' but '||/&&' have higher.
Carsten Milkau 06-Jul-2012 12:06
Beware the unusual order of bit-wise operators and comparison operators, this has often lead to bugs in my experience. For instance:

<?php if ( $flags & MASK  == 1) do_something(); ?>

will not do what you might expect from other languages. Use

<?php if (($flags & MASK) == 1) do_something(); ?>

in PHP instead.