Operator Precedence

Ma Mahalakshmi V Updated 14 Nov 2026
9 min read ·Lesson 45 of 256

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 Tutorial Index 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 Static Variables Variable Variables PHP Echo / Print PHP printf / sprintf PHP Data Types PHP Booleans PHP NULL PHP Strings String Functions Modify Strings Concatenate Strings Slicing Strings Escape Characters String Interpolation Heredoc and Nowdoc Search in Strings Multibyte Strings PHP Floats PHP Casting PHP Type Juggling PHP Math PHP Random Numbers PHP Constants PHP Magic Constants PHP Operators Arithmetic Operators Assignment Operators Comparison Operators Increment / Decrement Operators Logical Operators Null Coalescing Operator Spaceship Operator Operator Precedence PHP If...Else...Elseif PHP If PHP If Operators PHP If...Else PHP Shorthand if PHP Nested if PHP Switch PHP Match Alternative Syntax PHP Loops While Loop Do While Loop For Loop Foreach Loop Nested Loops Break Statement Continue Statement PHP Functions User-defined Functions Function Arguments Default Argument Values Pass by Reference Named Arguments Variadic Functions Return Values Type Declarations in Functions Recursive Functions Variable Functions Anonymous Functions Closures Arrow Functions First-class Callable Syntax PHP Arrays Indexed Arrays Associative Arrays Create Arrays Access Array Items Update Array Items Add Array Items Remove Array Items Sorting Arrays Multidimensional Arrays Array Destructuring Array Spread Operator Search in Arrays Merge Arrays array_map / array_filter / array_reduce Array Functions PHP Superglobals $GLOBALS $_SERVER $_REQUEST $_POST $_GET $_FILES $_COOKIE $_SESSION \$\_ENV PHP RegEx RegEx Patterns RegEx Modifiers preg_match preg_replace preg_split PHP RegEx Functions PHP Form Handling PHP Form Validation PHP Form Required PHP Form URL/E-mail Form Input Sanitizing Escaping Output (htmlspecialchars) Checkbox, Radio and Select Inputs Sticky Forms PHP Form Complete PHP Date and Time Date Formatting DateTime Class Timezones PHP Include Include vs Require PHP File Handling PHP File Open/Read PHP File Create/Write File Delete / Rename / Copy PHP Directories PHP CSV Files PHP File Upload PHP Cookies PHP Sessions PHP Filters PHP Filters Advanced PHP Callback Functions PHP JSON PHP Exceptions Error Handling Custom Error Handler Error Logging HTTP Headers and Redirects Output Buffering Sending Email PHP cURL Consuming REST APIs PHP Generators PHP What is OOP PHP Classes/Objects The $this Keyword PHP Properties PHP Methods PHP Constructor Constructor Property Promotion PHP Destructor PHP Access Modifiers Readonly Properties PHP Inheritance Method Overriding The final Keyword PHP Class Constants PHP Abstract Classes PHP Interfaces Polymorphism PHP Traits PHP Static Methods PHP Static Properties Late Static Binding Magic Methods Object Cloning Comparing Objects Anonymous Classes PHP Enums PHP Namespaces Autoloading Classes PHP Iterables Iterators Object Serialization Strict Types Union Types Nullable Types Mixed and Never Types Nullsafe Operator PHP Attributes PHP Fibers Readonly Classes Property Hooks (PHP 8.4) Asymmetric Visibility (PHP 8.4) Reflection API SPL Data Structures MySQL Database MySQL Connect MySQL Create DB MySQL Create Table MySQL Insert Data MySQL Get Last ID MySQL Insert Multiple MySQL Prepared MySQL Select Data MySQL Where MySQL Order By MySQL Delete Data MySQL Update Data MySQL Limit Data MySQL Joins with PHP Pagination with PHP PDO Introduction PDO Connect PDO Prepared Statements PDO Fetch Modes PDO Transactions PDO Error Handling PHP XML Parsers PHP SimpleXML Parser PHP SimpleXML - Get PHP XML Expat Parser PHP DOM Parser PHP XMLReader PHP XMLWriter AJAX Intro AJAX PHP AJAX Database AJAX XML AJAX Live Search AJAX Poll AJAX with JSON Security Introduction Password Hashing SQL Injection Prevention XSS Prevention CSRF Protection Session Security Secure Cookies File Upload Security Filesystem Security Error Reporting in Production Hiding PHP Encryption with Sodium PHP Configuration (php.ini) PHP Command Line (CLI) Composer PSR-4 Autoloading Installing Extensions (PECL / PIE) Debugging PHP OPcache & Performance Garbage Collection PHP-FPM Migrating to PHP 8 Project: Contact Form with Email Project: Login & Registration System Project: CRUD App with MySQL Project: Image Upload Gallery Project: Shopping Cart with Sessions Project: Simple Blog Project: REST API with PHP
Ask about this post
AI Ask about this post

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

Signed-in readers only.