Free tutorials in Hindi & English Daily computer, mobile and IT guides Beginner friendly learning
Blog · PHP · 04 Jul 2026 · Hindi + English

== vs === in PHP: Why Type Juggling Bites

== compares after converting types (0 == "a" surprises); === compares value AND type with no conversion. Famous traps table and why login code must use ===.

The one-line answer

== compares values AFTER converting both sides to a common type (loose); === compares value AND type with zero conversion (strict). The conversion step — called type juggling — is where PHP quietly surprises you.
<?php
var_dump(5 == "5");     // bool(true)  - string "5" converted to 5
var_dump(5 === "5");    // bool(false) - int vs string: types differ
?>

The famous traps table

Comparison== result=== resultWhy == says that
0 == "abc"false (PHP 8) / true (PHP 7!)falsePHP 7 converted "abc" to 0
"1" == "01"truefalseBoth look numeric → compared as numbers
"10" == "1e1"truefalse1e1 is scientific notation for 10
100 == "1e2"truefalseSame scientific-notation juggling
0 == falsetruefalsefalse converts to 0
null == falsetruefalseBoth are falsy
"" == nulltruefalseBoth are falsy
Your hosting note (PHP 7.2/7.3): on PHP 7, 0 == "abc" is TRUE — any non-numeric string converts to 0. PHP 8 changed this rule. Code that "worked" on PHP 7 by accident can flip behaviour after an upgrade — one more reason to write === from day one.

Where it burns real applications: security

<?php
// OTP / token comparison - the classic vulnerability:
$saved_otp = "0e462097431906509019562988736854";  // hash-like string
$user_otp  = "0e830400451993494058024219903391";  // different string!

var_dump($saved_otp == $user_otp);    // bool(true)  !!!
// Both look like scientific notation: 0e{digits} = 0 x 10^n = 0
// 0 == 0 -> ATTACKER GETS IN. This is the "magic hash" attack.

var_dump($saved_otp === $user_otp);   // bool(false) - safe
?>

This is not theoretical — "magic hashes" (strings like 0e123...) have broken real login systems. Rule: OTPs, tokens, passwords, hashes — always === (and for password hashes specifically, password_verify(), and hash_equals() for tokens).

The strpos trap — where === is compulsory

<?php
$pos = strpos("Hello World", "Hello");   // returns 0 (found at position 0!)

if ($pos == false)  { echo "Not found"; }   // WRONG - prints "Not found"!
                                             // because 0 == false is true

if ($pos === false) { echo "Not found"; }   // CORRECT - stays silent
?>

Functions like strpos(), array_search() return 0 or false — meaningfully different values that == cannot tell apart. The PHP manual itself marks these functions with a big warning to use ===.

Rule of thumb

  • Default to === (and !==) everywhere. It never surprises.
  • Use == only when you consciously WANT type conversion — e.g., comparing form input "5" (string) to int 5 — and even there, better to cast first: (int)$_POST['qty'] === 5.
  • Interview line: "== juggles types before comparing, so 0, '', null and false blur together and magic hashes break security; === compares value plus type with no conversion — the professional default."

One-line answer

== दोनों तरफ को common type में बदलकर values compare करता है (loose); === value AND type बिना किसी conversion के compare करता है (strict). यही conversion step — जिसे type juggling कहते हैं — वह जगह है जहां PHP चुपचाप चौंकाता है.
<?php
var_dump(5 == "5");     // bool(true)  - string "5" बदलकर 5 हुई
var_dump(5 === "5");    // bool(false) - int vs string: types अलग
?>

Famous traps table

Comparison== result=== result== ऐसा क्यों कहता है
0 == "abc"false (PHP 8) / true (PHP 7!)falsePHP 7 "abc" को 0 बना देता था
"1" == "01"truefalseदोनों numeric दिखे → numbers की तरह compare
"10" == "1e1"truefalse1e1 = 10 की scientific notation
100 == "1e2"truefalseवही scientific-notation juggling
0 == falsetruefalsefalse बदलकर 0 होता है
null == falsetruefalseदोनों falsy
"" == nulltruefalseदोनों falsy
आपकी hosting के लिए note (PHP 7.2/7.3): PHP 7 पर 0 == "abc" TRUE है — कोई भी non-numeric string 0 बन जाती है. PHP 8 ने यह rule बदला. जो code PHP 7 पर "संयोग से चलता" था वह upgrade के बाद behaviour पलट सकता है — पहले दिन से === लिखने की एक और वजह.

असली applications में कहां जलाता है: security

<?php
// OTP / token comparison - classic vulnerability:
$saved_otp = "0e462097431906509019562988736854";  // hash-जैसी string
$user_otp  = "0e830400451993494058024219903391";  // अलग string!

var_dump($saved_otp == $user_otp);    // bool(true)  !!!
// दोनों scientific notation दिखीं: 0e{digits} = 0 x 10^n = 0
// 0 == 0 -> ATTACKER अंदर. यही "magic hash" attack है.

var_dump($saved_otp === $user_otp);   // bool(false) - safe
?>

यह theoretical नहीं — "magic hashes" (0e123... जैसी strings) असली login systems तोड़ चुकी हैं. Rule: OTPs, tokens, passwords, hashes — हमेशा === (और password hashes के लिए खासतौर पर password_verify(), tokens के लिए hash_equals()).

strpos trap — जहां === compulsory है

<?php
$pos = strpos("Hello World", "Hello");   // 0 return हुआ (position 0 पर मिला!)

if ($pos == false)  { echo "Not found"; }   // GALAT - "Not found" छापता है!
                                             // क्योंकि 0 == false true है

if ($pos === false) { echo "Not found"; }   // SAHI - चुप रहता है

strpos(), array_search() जैसे functions 0 या false return करते हैं — meaningfully अलग values जिन्हें == अलग कर ही नहीं सकता. PHP manual खुद इन functions पर === use करने की बड़ी warning लगाता है.

Rule of thumb

  • हर जगह default === (और !==). यह कभी नहीं चौंकाता.
  • == सिर्फ तब जब आपको जानबूझकर type conversion CHAHIYE — जैसे form input "5" (string) को int 5 से मिलाना — और वहां भी बेहतर है पहले cast करना: (int)$_POST['qty'] === 5.
  • Interview line: "== compare से पहले types juggle करता है, जिससे 0, '', null और false आपस में घुल जाते हैं और magic hashes security तोड़ते हैं; === value plus type बिना conversion compare करता है — professional default."

Frequently Asked Questions

What is the difference between == and === in PHP?

== converts both sides to a common type before comparing values (type juggling), while === compares both value and type with no conversion — so 5 == "5" is true but 5 === "5" is false.

What is the magic hash vulnerability?

Strings like "0e12345..." look like scientific notation, so == converts them all to 0 and two different hashes compare as equal — letting attackers bypass OTP or hash checks; === (or hash_equals) prevents it.

Why must strpos() results be checked with ===?

strpos() returns 0 when the match is at the start and false when not found; 0 == false is true, so only $pos === false correctly detects the not-found case.