PHP operator precedence is the ranking that decides which part of a line runs first. PHP does not read your code left to right. It looks at every operator in the line, finds the highest-ranked one, and starts there. Get the ranking wrong and your maths is wrong โ silently, with no error to tell you.
Start with a line that lies to you
Two short sums. Predict both before you read on.
<?php
echo 10 - 4 - 3;
echo "<br>";
echo 2 ** 3 ** 2;
?>
Output

The first is 3, which is what you expected. The second is 512, not 64.
Both lines have two copies of the same operator, so precedence cannot break the tie. Something else does, and we come back to it below.
The PHP operator precedence table
Highest first. Anything on a higher row runs before anything on a lower row.
| Operators | Associativity | Notes |
** | right | Exponent |
++ -- (int) (string) @ | โ | Increment and casts |
instanceof | โ | |
! | โ | Higher than every comparison |
* / % | left | |
+ - | left | |
<< >> | left | Bitwise shifts, rarely used |
. | left | Below + since PHP 8 |
< <= > >= | โ | |
== != === !== <=> | โ | |
& then ^ then | | left | Bitwise, rarely used |
&& | left | |
|| | left | |
?? | right | Null coalescing |
? : | โ | Ternary |
= += -= .= ??= | right | Assignment |
and | left | |
xor | left | |
or | left | Lowest of everything |
You do not need to memorise this. You need to know three rows: ! sits above the comparisons, . now sits below +, and and and or sit below =. Those three cause almost every real bug. The rest of this post is each one in turn.
Associativity: what happens on a tie
When two operators have the same rank, PHP needs a tie-breaker. That is associativity, and it is the third column above.
Left means group from the left. 10 - 4 - 3 becomes (10 - 4) - 3, which is 3.
Right means group from the right. ** is the only common right-associative arithmetic operator, so 2 ** 3 ** 2 becomes 2 ** (3 ** 2). That is 2 to the power of 9, which is 512.
Assignment is right-associative too, which is why $a = $b = 5 works. The right-hand assignment runs first and hands its value to the left.
The dot moved in PHP 8
This one changed under everybody's feet, so old tutorials get it wrong.
<?php
echo "Sum: " . 1 + 2;
?>
Output

In PHP 8 this prints Sum: 3. The dot now ranks below +, so PHP adds first and joins second.
On PHP 7 the same line grouped as ("Sum: " . 1) + 2 โ it tried to add 2 to the string "Sum: 1" and failed. If you find a Stack Overflow answer telling you to always bracket your maths inside a concatenation, that is why. The advice is now unnecessary, but it is still not harmful.
Why ! catches everyone
! ranks above every comparison operator. That is almost never what people mean.
<?php
$age = 5;
var_dump(!$age > 10);
var_dump(!($age > 10));
?>
Output

The first is false. The second is true. Same characters, one pair of brackets apart.
Line one runs !$age first. 5 is truthy, so !$age is false. PHP then compares false > 10, converts both sides to booleans, and reports false.
Line two is what you meant: check whether 5 is greater than 10, then flip it.
Why and is not &&
The lowest three rows of the table are and, xor and or โ below assignment.
<?php
$a = true && false;
$b = true and false;
var_dump($a);
var_dump($b);
?>
Output

$a is false. $b is true, because = outranks and, so PHP assigns true and then throws the and false away.
This one has enough corners to deserve its own page โ see PHP logical operators: and, or, && and || explained.
Brackets are always allowed
Nothing outranks a bracket. When a line mixes operators from different rows, add them.
<?php
$price = 100;
$qty = 3;
$discount = 10;
echo $price * $qty - $discount / 2;
echo "<br>";
echo ($price * $qty - $discount) / 2;
?>
Output

The first line gives 295. * and / both outrank -, so PHP works out 300 and 5 before subtracting.
The second gives 145 โ total, minus the discount, halved. That is almost certainly what a "half price after discount" line was meant to say.
PHP operator precedence never has to be a guessing game. Brackets cost you two characters and remove the question entirely.
Common questions about PHP operator precedence
The precedence questions that send people searching most often.
What is operator precedence in PHP?
It is the ranking that decides which operator runs first when a line has several. Multiplication outranks addition, so 2 + 3 * 4 is 14 rather than 20. Brackets outrank everything.
Which PHP operator has the highest precedence?
**, the exponent operator, is the highest of the ordinary operators. Brackets are not really an operator, but nothing beats them, so they are the practical answer.
Which PHP operator has the lowest precedence?
or. Below it there is nothing. and and xor are the next two up, and all three sit under the assignment operator =.
What is the difference between precedence and associativity?
Precedence ranks different operators against each other. Associativity breaks the tie between operators of the same rank. - is left-associative, so 10 - 4 - 3 is 3. ** is right-associative, so 2 ** 3 ** 2 is 512.
Did PHP operator precedence change in PHP 8?
Yes. The concatenation operator . dropped below + and -. So "Sum: " . 1 + 2 prints Sum: 3 on PHP 8, where PHP 7 raised an error.
What is next
Precedence is the rule underneath a lot of confusing PHP. Two operators that read identically can do different things, and now you know why.
Next, see how it plays out with the word operators in PHP logical operators, or go back to the full set in PHP operators: arithmetic, comparison and logical.
Loading comments...