PHP type coercion in strict mode vs non-strict — full breakdown
Concept
PHP's type coercion behaves very differently depending on whether declare(strict_types=1) is present at the top of the calling file.
Non-strict mode (default, no declaration):
- PHP coerces scalar types automatically on function calls.
int → float: Always safe.float → int: Truncates decimal part (not rounds).3.9 → 3.string → int/float: If the string starts with a number, extracts it."42abc" → 42,"abc" → 0.bool → int:true → 1,false → 0.null → int/float/string/bool:null → 0,null → "",null → false.int/float → string: Converts to string representation.
Strict mode (declare(strict_types=1) in the CALLING file):
- Only exact type accepted (with one exception: int IS accepted where float is expected).
- Passing
"42"whereintis expected →TypeError. - Passing
3.9whereintis expected →TypeError. - The declaration affects calls FROM that file, not the function being called.
Important: strict_types applies to the FILE that makes the call, not the file that defines the function. A function defined without strict_types can still be called strictly from a file that HAS strict_types=1.
Union types (PHP 8.0+): int|string accepts either type. More explicit than coercion.
declare(strict_types=1) must be the very first statement in the file — before any code, before namespace, after only <?php and optional BOM.
settype() / (int) / intval(): Explicit coercion in PHP — always works regardless of strict mode (these are type casts, not type declarations).
Code Example
<?php
// ============================================================
// NON-STRICT MODE — default PHP behavior
// ============================================================
function addNumbers(int $a, int $b): int
{
return $a + $b;
}
// Without strict_types:
addNumbers(1, 2); // 3 — exact match, fine
addNumbers(1.9, 2.1); // 3 — floats truncated to 1 and 2
addNumbers("5", "3"); // 8 — strings coerced to ints
addNumbers("5abc", "3"); // 8 — "5abc" → 5 (with E_DEPRECATED in PHP 8.1)
// String to number coercion
$x = "10" + 5; // 15 — PHP coerces "10" to 10
$y = "10abc" + 5; // 15 — numeric string prefix extracted
$z = "abc" + 5; // 5 — non-numeric string → 0
// Null coercion
function greet(?string $name): string
{
return "Hello " . ($name ?? 'stranger');
}
greet(null); // "Hello stranger"
// Bool to int
var_dump((int) true); // 1
var_dump((int) false); // 0
var_dump((bool) 0); // false
var_dump((bool) ""); // false
var_dump((bool) "0"); // false — only "0" is falsy string
var_dump((bool) "false"); // TRUE — non-empty, non-"0" string is truthy!