Operator Precedence
When an expression mixes several operators, PHP does not evaluate them strictly left to right — it follows a precedence order, exactly like the "multiplication before addition" rule from arithmetic class. Operators of the same precedence are then resolved by associativity, which decides whether grouping happens left-to-right or right-to-left. Getting this wrong produces code that runs without error but computes the wrong answer, which is a far more dangerous kind of bug than one that crashes loudly.
Precedence with arithmetic
The example everyone recognizes from math also applies directly in PHP: multiplication and division bind tighter than addition and subtraction, so they are evaluated first even though addition appears first when read left to right.
Multiplication before addition
<?php $result = 2 + 3 * 4; // not (2 + 3) * 4 echo $result; // 14, because 3 * 4 is evaluated first
14
Associativity
When two operators share the same precedence, associativity breaks the tie. Most arithmetic operators are left-associative (grouped left to right), but a few — like the exponentiation operator ** and the assignment operator = — are right-associative.
Left vs right associativity
<?php echo 10 - 3 - 2; // 5, left-assoc: (10 - 3) - 2 echo "\n"; echo 2 ** 3 ** 2; // 512, right-assoc: 2 ** (3 ** 2), not (2 ** 3) ** 2
5 512
A reference table
This is not the complete PHP precedence table (the official one has dozens of entries once you include type casts, instanceof, and bitwise operators), but it covers the operators that come up in everyday code, ordered from highest precedence at the top to lowest at the bottom.
Precedence | Operators | Associativity |
|---|---|---|
1 (highest) |
| Right |
2 |
| Non-associative |
3 |
| Left |
4 |
| Left |
5 |
| Left |
6 |
| Non-associative |
7 |
| Non-associative |
8 |
| Left |
9 |
| Left |
10 |
| Right |
11 |
| Right |
12 |
| Left |
13 |
| Left |
14 (lowest) |
| Left |
Real bugs caused by precedence
The Logical Operators page covers the and/or versus &&/|| trap in depth — it is the single most common real-world bug caused by precedence, because = binds tighter than and/or but looser than &&/||. A second common mistake mixes string concatenation with comparison or arithmetic without parentheses.
Concatenation vs addition without parentheses
<?php $count = 3; // Intent: print "Total: 8" echo "Total: " . $count + 5; // TypeError in PHP 8!
Fixed with parentheses
<?php $count = 3; echo "Total: " . ($count + 5); // Total: 8
Total: 8
Ternary chaining
Nested ternary expressions are another classic precedence pitfall. As of PHP 8, chaining ternaries without explicit parentheses is a fatal compile-time error rather than a silent left-to-right guess, which is PHP forcing you to be explicit about something that used to be a common source of bugs.
Nested ternaries need parentheses in PHP 8
<?php $score = 72; // Must parenthesize nested ternaries explicitly in PHP 8+ $grade = ($score >= 90) ? "A" : (($score >= 70) ? "B" : "C"); echo $grade; // B
B
**binds tighter than unary minus and is right-associative.&&binds tighter than||, which binds tighter than??.and/or/xorsit below=in precedence — a frequent source of bugs.PHP 8 requires explicit parentheses around nested ternary expressions.