Types catch bugs at the call site and make static analysis and IDE support work.
By default PHP runs in coercive mode: a scalar argument of the wrong type is converted if possible, so passing "5" to an int parameter gives 5. Put this as the very first statement of a file to switch to strict mode:
declare(strict_types=1);Now only an exact scalar type is accepted (the one exception is an int passed to a float). The setting applies to calls made from that file, not to the functions defined in it, so every file opts in for itself. Most modern codebases put it in every file.
Types you can declare on parameters, returns and properties:
- Scalars
int,float,string,bool, plusarray,callable,iterable,object, class and interface names. - Nullable
?Userand unionint|string(PHP 8.0); intersectionCountable&Iterator(8.1); combinations like(A&B)|null(8.2). mixed(anything),void(returns nothing),never(always throws or exits),static(the called class), andnull,falseandtrueas standalone types (8.2).
A mismatch throws a TypeError. Typed properties are uninitialized until assigned, and reading one before that throws an Error.
Implicitly nullable parameters, function f(User $u = null), are deprecated in PHP 8.4; write ?User $u = null.
Example
<?php
declare(strict_types=1);
function area(float $w, float $h): float {
return $w * $h;
}
function findId(int|string $key): ?int {
return is_numeric($key) ? (int) $key : null;
}
function fail(string $msg): never {
throw new RuntimeException($msg);
}
echo area(2, 3.5), "\n"; // 7 (int to float is allowed)
var_dump(findId('x')); // NULL
try {
area("2", 3); // string not accepted in strict mode
} catch (TypeError $e) {
echo "TypeError\n"; // TypeError
}Remember
- declare(strict_types=1) affects calls made from that file
- Use unions, nullables and never to describe real contracts
- Type mismatches throw TypeError instead of silently converting
Watch out for
- Expecting strict_types in a library file to protect its functions from callers in non-strict files.