Operator Precedence

Su Subhalakshmi Chandran Updated 17 Oct 2026
9 min read ·Lesson 27 of 102
In this post

What Is Operator Precedence? In simple terms: When an expression contains several operators, precedence decides which operator is applied first — just as multiplication is done before addition in math

What Is Operator Precedence?

In simple terms: When an expression contains several operators, precedence decides which operator is applied first — just as multiplication is done before addition in mathematics.

Technically: Every PHP operator has a precedence level. Operators with higher precedence bind more tightly to their operands. When operators share the same level, associativity decides the grouping: left to right, right to left, or not allowed at all (non-associative).

echo 2 + 3 * 4;   // 14, because * binds tighter than +

PHP reads this as 2 + (3 * 4), not (2 + 3) * 4.

Why It Matters

Most precedence rules feel natural, but some do not — especially when concatenation, null coalescing, logical keywords, negation, or bitwise operators are mixed with other operators. Many subtle bugs come from an expression being grouped differently than the author intended. Understanding precedence lets you read existing code correctly and know when parentheses are required.


Precedence Table

From highest precedence (applied first) to lowest:

LevelOperatorsAssociativityNotes
1clone, new—Object creation
2**rightExponentiation
3+ - (unary), ++, --, ~, (int), (float), (string), (array), (object), (bool), @—Unary operators and casts
4instanceofleftType check
5!—Logical NOT
6* / %leftMultiplicative
7+ -leftAdditive
8<< >>leftBit shift
9.leftConcatenation (lower than +/- since PHP 8.0)
10< <= > >=non-associativeOrdering comparison
11== != === !== <> <=>non-associativeEquality
12&leftBitwise AND
13^leftBitwise XOR
14|leftBitwise OR
15&&leftLogical AND
16||leftLogical OR
17??rightNull coalescing
18? :non-associativeTernary
19= += -= *= /= .= %= **= ??= &= |= ^= <<= >>=rightAssignment
20yield from, yield, print—
21andleftLogical AND (keyword)
22xorleftLogical XOR (keyword)
23orleftLogical OR (keyword)

You do not need to memorize this table. The practical skill is knowing where the surprises are — covered in the rest of this lesson.


Associativity

When an expression uses several operators of the same precedence, associativity decides the grouping.

Example

<?php
echo 10 - 4 - 3 . "\n";     // left:  (10 - 4) - 3
echo 100 / 10 / 2 . "\n";   // left:  (100 / 10) / 2
echo 2 ** 3 ** 2 . "\n";    // right: 2 ** (3 ** 2)

$a = $b = 5;                // right: $a = ($b = 5)
echo "$a $b\n";

Output

3
5
512
5 5
  • Left-associative operators (-, /, ., &&, …) group from left to right, which matches normal reading order.
  • Right-associative operators (**, ??, =) group from right to left. That is why $a = $b = 5 assigns 5 to both variables and $a ?? $b ?? $c checks $a first, then $b, then $c.

Non-Associative Operators

Comparison operators cannot be chained:

<?php
$x = 5;
var_dump(1 < $x < 10);

Result

PHP Parse error:  syntax error, unexpected token "<"

PHP refuses to guess what 1 < $x < 10 means. Write the range check explicitly: 1 < $x && $x < 10.


Arithmetic

<?php
var_dump(2 + 3 * 4);
var_dump((2 + 3) * 4);
var_dump(-3 ** 2);
var_dump((-3) ** 2);

Output

int(14)
int(20)
int(-9)
int(9)

** has higher precedence than unary minus, so -3 ** 2 is -(3 ** 2). Use parentheses when the base is negative.


Concatenation and Arithmetic

<?php
echo "Sum: " . 4 + 5 . "\n";
echo "Product: " . 4 * 5 . "\n";
echo "Sum: " . (4 + 5) . "\n";

Output (PHP 8.0 and newer)

Sum: 9
Product: 20
Sum: 9

Since PHP 8.0, + and - have higher precedence than ., so the addition happens first. In PHP 7, ., +, and - had the same precedence and were evaluated left to right, which produced "Sum: 4" + 5 — a warning and a wrong result. Code that must behave the same in both versions, and code that should be easy to read, uses parentheses as in the third line.


Casts

Casts are unary operators with high precedence. They apply only to the value directly after them:

<?php
var_dump((int) "3.7" + 0.5);
var_dump((int) ("3.7" + 0.5));

Output

float(3.5)
int(4)
  • First line: (int) "3.7" is 3, then 3 + 0.5 is 3.5.
  • Second line: the parentheses make PHP add first (4.2) and then cast to 4.

! and instanceof

instanceof has higher precedence than !:

<?php
$date = new DateTime();

var_dump(!$date instanceof DateTime);
var_dump(!($date instanceof DateTime));

Output

bool(false)
bool(false)

Both lines mean "not an instance of DateTime", because instanceof is applied before !. The first form works, but the parenthesized version is clearer to readers who do not remember this rule.

By contrast, ! binds tighter than comparison operators, so !$count > 0 means (!$count) > 0, not !($count > 0) — see Logical Operators.


Bitwise Operators and Comparisons

Bitwise &, ^, and | have lower precedence than == and other comparisons:

<?php
$flags = 5;   // binary 0101
$mask = 3;    // binary 0011

var_dump($flags & $mask == 3);
var_dump(($flags & $mask) == 3);

Output

int(1)
bool(false)
  • First line: PHP evaluates $mask == 3 first (true), then 5 & true, which is 5 & 1 = 1. The result is an integer, not the intended comparison.
  • Second line: the parentheses perform the bitwise AND first (0101 & 0011 = 0001 = 1) and then compare 1 == 3.

Always parenthesize bitwise operations inside comparisons.


Logical Operators and Assignment

OperatorsPrecedence Relative to =
&&, ||, ??, ?:Higher — evaluated before the assignment
and, xor, orLower — the assignment happens first
<?php
$x = true && false;
$y = true and false;

var_dump($x, $y);

Output

bool(false)
bool(true)

$y = true and false is grouped as ($y = true) and false. This is the main reason to prefer && and || over and and or.

&& Before ||

<?php
var_dump(true || false && false);
var_dump((true || false) && false);

Output

bool(true)
bool(false)

&& binds tighter than ||, so the first line is true || (false && false).


Null Coalescing

?? has lower precedence than arithmetic, concatenation, and comparison, so it often applies to a larger part of the expression than intended:

<?php
$price = 100;
$qty = 3;

var_dump($price ?? 0 * $qty);
var_dump(($price ?? 0) * $qty);

Output

int(100)
int(300)

The first line means $price ?? (0 * $qty). Wrap ?? in parentheses whenever it appears inside a larger expression. More examples are in Null Coalescing Operator.


Nested Ternaries Require Parentheses

The ternary operator is non-associative since PHP 8.0. Nesting it without parentheses is a compile-time error:

<?php
$score = 75;
echo $score >= 90 ? 'A' : $score >= 75 ? 'B' : 'C';

Result

PHP Fatal error:  Unparenthesized `a ? b : c ? d : e` is not supported. Use either `(a ? b : c) ? d : e` or `a ? b : (c ? d : e)`

In PHP 7 and earlier, this expression was silently grouped from the left — the opposite of most other languages — and produced wrong results, which is why PHP 8 forbids it. Add parentheses:

<?php
$score = 75;
echo $score >= 90 ? 'A' : ($score >= 75 ? 'B' : 'C');

Output

B

For more than two branches, match (true) or if/elseif is usually clearer than nested ternaries (see PHP Match).


Object Creation and Method Calls (PHP 8.4)

Before PHP 8.4, calling a method directly on a newly created object required wrapping the new expression in parentheses. PHP 8.4 removed that requirement:

<?php
class Greeting
{
    public function __construct(private string $name) {}

    public function text(): string
    {
        return "Hello, {$this->name}!";
    }
}

echo (new Greeting('Asha'))->text() . "\n";  // all PHP versions
echo new Greeting('Bala')->text() . "\n";    // PHP 8.4+

Output

Hello, Asha!
Hello, Bala!

The second form is a parse error on PHP 8.3 and older. Use the parenthesized form if your code must support older versions.


Precedence Is Not Evaluation Order

Precedence determines how an expression is grouped, not necessarily the order in which operands are evaluated. For example, in $a + $b * $c, precedence tells you that $b * $c is one group, but PHP does not guarantee whether $a is read before or after that group. This rarely matters — unless operands have side effects:

$i = 1;
echo $i + $i++;   // result is not guaranteed by the language

The PHP manual explicitly warns that such code may behave differently between versions. Never read and modify the same variable in a single expression.


Practical Example: Making a Complex Condition Readable

A signup rule says: users may register if they are adults in India, or if they are at least 13 and a guardian has given consent.

Hard to Read

<?php
$age = 15;
$country = 'IN';
$hasGuardianConsent = true;

$canRegister = $age >= 18 && $country === 'IN' || $hasGuardianConsent && $age >= 13;

var_dump($canRegister);

Output

bool(true)

The result is correct, but only because && binds tighter than ||. A reader must know the precedence rules to verify it, and a small edit (for example, adding or) could silently change the meaning.

Clear Version

<?php
$age = 15;
$country = 'IN';
$hasGuardianConsent = true;

$isAdultInIndia = $age >= 18 && $country === 'IN';
$isTeenWithConsent = $age >= 13 && $hasGuardianConsent;

$canRegister = $isAdultInIndia || $isTeenWithConsent;

var_dump($canRegister);

Output

bool(true)

Why the Second Version Is Better

  1. Each sub-rule has a name that describes the business rule.
  2. Each line contains only one kind of logical operator, so no precedence knowledge is needed.
  3. Each part can be checked or tested separately.

When a single expression grows too long, splitting it into named variables is usually better than adding more parentheses.


Common Mistakes

MistakeWhat PHP DoesFix
-2 ** 2-(2 ** 2) = -4(-2) ** 2
$a & $mask == 3$a & ($mask == 3)($a & $mask) == 3
'Hi ' . $name ?? 'Guest'('Hi ' . $name) ?? 'Guest''Hi ' . ($name ?? 'Guest')
$ok = $a and $b($ok = $a) and $b$ok = $a && $b
!$x > 0(!$x) > 0!($x > 0) or $x <= 0
$a ? 'x' : $b ? 'y' : 'z'Fatal error in PHP 8Add parentheses or use match
1 < $x < 10Parse error1 < $x && $x < 10

Best Practices

  • Use parentheses whenever an expression mixes different kinds of operators and the grouping is not obvious at a glance.
  • Use && / || instead of and / or.
  • Wrap ??, bitwise operations, and nested ternaries in parentheses.
  • Split long expressions into well-named variables.
  • Never modify and read the same variable within one expression.

Official reference: https://www.php.net/manual/en/language.operators.precedence.php

0 Comments

Reviewed before they appear

No comments yet.

PHP
PHP Home PHP Switch PHP Match Alternative Syntax PHP Loops While Loop Do While Loop For Loop Foreach Loop Nested Loops Break Statement PHP Home PHP Intro PHP Install PHP Built-in Web Server PHP Syntax PHP Tags PHP and HTML PHP Comments PHP Multiline Comments PHP Variables Variables Scope PHP Casting Logical Operators Null Coalescing Operator Spaceship Operator Operator Precedence Continue Statement Modify Strings PHP If...Else...Elseif PHP If Modify Strings PHP If Operators PHP Functions Concatenate Strings PHP If...Else Slicing Strings User-defined Functions Slicing Strings PHP Shorthand if Escape Characters Default Argument Values PHP Nested if Pass by Reference String Interpolation Named Arguments PHP File Upload Variadic Functions Return Values Search in Strings Multibyte Strings Type Declarations in Functions PHP Numbers PHP Math PHP Floats PHP Random Numbers PHP Constants PHP Properties PHP Methods PHP Constructor Constructor Property Promotion PHP Cookies PHP Destructor PHP Access Modifiers Readonly Properties PHP Sessions PHP Inheritance Method Overriding PHP Filters The final Keyword CSRF Protection PHP Filters Advanced Session Security Secure Cookies PHP Magic Constants File Upload Security PHP Callback Functions PHP Operators Filesystem Security PHP JSON Arithmetic Operators Error Reporting in Production Hiding PHP Assignment Operators PHP Configuration (php.ini) Comparison Operators PHP Command Line (CLI) PHP Exceptions Increment / Decrement Operators Migrating to PHP 8 PHP Form Validation PHP Form Required PHP Form URL/E-mail Error Handling Form Input Sanitizing Escaping Output (htmlspecialchars) Custom Error Handler Checkbox, Radio and Select Inputs Sticky Forms PHP Form Complete PHP Date and Time Date Formatting
Ask about this post
AI Ask about this post

Ask questions about Operator Precedence and get answers drawn from it.

Signed-in readers only.