Type Juggling and Conversion
PHP converts values between types automatically when an operation needs it — adding a number to a numeric string, using a number as a condition, comparing a string with an integer. This "type juggling" is convenient, but its rules have surprised many developers. This lesson explains the rules, how to convert explicitly, and how strict comparisons and strict types keep you safe.
Automatic conversion
Arithmetic operators convert their operands to numbers; the dot operator converts to strings:
<?php var_dump("5" + 3); // numeric string -> number var_dump("2.5" * 2); var_dump(5 . 3); // numbers -> strings, then joined var_dump("10" == 10); var_dump(true + true);
int(8) float(5) string(2) "53" bool(true) int(2)
Form input, URL parameters, database results and file contents usually arrive as strings, so this conversion happens all the time.
When strings aren't numbers
PHP 8 is stricter than older versions. A string that only starts with a number is used with a warning; a string that isn't numeric at all throws a TypeError:
<?php var_dump("12 apples" + 3); var_dump("apples" + 3);
Warning: A non-numeric value encountered in main.php on line 3
int(15)
Fatal error: Uncaught TypeError: Unsupported operand types: string + int in main.php:4
Stack trace:
#0 {main}
thrown in main.php on line 4Explicit casts
Write the target type in parentheses to convert explicitly. Casting never throws; it always produces something:
<?php var_dump((int) "42"); var_dump((int) "42.9"); // truncated, not rounded var_dump((int) "abc"); // no digits: 0 var_dump((float) "3.5kg"); var_dump((string) 7.0); var_dump((bool) "0"); var_dump((array) "solo");
int(42)
int(42)
int(0)
float(3.5)
string(1) "7"
bool(false)
array(1) {
[0]=>
string(4) "solo"
}The functions intval(), floatval(), strval() and boolval() do the same as the casts. Use the short cast names (int), (float), (bool) and (string) — the long forms such as (integer) and (boolean) are deprecated as of PHP 8.5.
Because casts accept anything, they're the wrong tool for validating input: (int) "abc" silently becomes 0. To check that input really is a number, use filter_var:
<?php foreach (["42", "4.2", "abc", " 7 ", "-3"] as $input) { $n = filter_var($input, FILTER_VALIDATE_INT); echo str_pad("'$input'", 7), $n === false ? "invalid" : "valid: $n", "\n"; }
'42' valid: 42 '4.2' invalid 'abc' invalid ' 7 ' valid: 7 '-3' valid: -3
Truthy and falsy values
When a value is used as a condition, PHP converts it to a boolean. These values are falsy; everything else is truthy:
false,0,0.0,null- the empty string
""and the string"0" - an empty array
[]
<?php foreach ([0, 1, -1, "", "0", "0.0", " ", "false", [], [0], null] as $v) { echo str_pad(json_encode($v), 8), $v ? "truthy" : "falsy", "\n"; }
0 falsy 1 truthy -1 truthy "" falsy "0" falsy "0.0" truthy " " truthy "false" truthy [] falsy [0] truthy null falsy
Note the odd ones: "0" is falsy but "0.0" and "false" are truthy. When the distinction matters, compare explicitly instead of relying on truthiness.
== versus ===
The loose equality operator == converts types before comparing. The strict operator === requires the same type and value:
<?php var_dump(1 == "1"); // true: string converted var_dump(1 === "1"); // false: different types var_dump(0 == ""); // false in PHP 8 var_dump(null == false); // true var_dump(null === false); // false var_dump("abc" == 0); // false in PHP 8 (true in PHP 7!) var_dump("1e3" == "1000"); // true: both numeric strings
bool(true) bool(false) bool(false) bool(true) bool(false) bool(false) bool(true)
PHP 8 fixed the most notorious cases — comparing a number with a non-numeric string now compares them as strings — but == still has surprises like "1e3" == "1000". Use === and !== by default, and reach for == only when you deliberately want conversion.
The same applies to functions that search: in_array and array_search compare loosely unless you pass true as the third argument.
<?php $allowed = ["1", "2", "3"]; var_dump(in_array(1, $allowed)); // loose: true var_dump(in_array(1, $allowed, true)); // strict: false
bool(true) bool(false)
Strict types for function calls
With declare(strict_types=1) at the top of a file, PHP stops converting arguments to match a function's declared parameter types — the one exception being that an int is allowed where a float is expected. Without it, "5" is quietly converted to 5 for an int parameter:
<?php function square(int $n): int { return $n * $n; } var_dump(square("5")); // allowed in the default (coercive) mode var_dump(square(5.0)); // a float with no fraction is accepted too var_dump(square(5.5));
int(25) int(25) Deprecated: Implicit conversion from float 5.5 to int loses precision in main.php on line 3 int(25)
Lesson 29 covers type declarations and strict mode in depth.
Try it yourself
Validate a list of ages typed by users: accept whole numbers from 0 to 130 and report the rest.
'34' accepted as 34 'abc' rejected '-5' rejected '131' rejected '27' accepted as 27 '12.5' rejected '' rejected