PHP converts types automatically when an operation needs it. This is called type juggling. It is convenient, and it is also a classic source of bugs.
Numbers inside strings
<?php
var_dump("5" + "5");
var_dump("5" . "5");
var_dump("2.5" * 2);
int(10)
string(2) "55"
float(5)
The + operator wants numbers, so PHP converts the strings. The . operator wants strings, so it joins them.
Strings that only start like a number
<?php
var_dump("5 apples" + 1);
Warning: A non-numeric value encountered in /path/to/index.php on line 2
int(6)
Strings that are not numeric at all
Since PHP 8, arithmetic on a string that is not a number throws an error.
<?php
try {
echo "abc" + 1;
} catch (TypeError $e) {
echo $e->getMessage();
}
Unsupported operand types: string + int
Loose comparison
The == operator also juggles types, and PHP 8 made these rules saner.
<?php
var_dump(0 == "a"); // false in PHP 8, was true in PHP 7
var_dump("1" == "01"); // both numeric strings, so compared as numbers
var_dump(100 == "1e2"); // "1e2" is the number 100
var_dump(null == false);
bool(false)
bool(true)
bool(true)
bool(true)
Why this is dangerous
A loose comparison can let a wrong value through.
<?php
$role = "0";
if ($role == false) {
echo "Treated as no role";
}
Treated as no role
The safe habit
- Use
===and!==instead of==and!=. See Equality vs Identity. - Turn on strict typing in your files.
- Convert on purpose with a cast, so the next person sees what you meant.