Chapter 1: Scalar Type Hints
PHP 5 introduced the ability to require function parameters to be of a certain type. This provides a safeguard against invalid uses, like passing a UNIX timestamp to a method which expects a DateTime object. It also makes it clear to other developers how the function should be used. For example, compare the following method signatures with and without type hints:
// No type hint:
function getNextWeekday($date) { /*...*/ }
// Class type hint (PHP 5):
function getNextWeekday(DateTime $date) { /*...*/ }
These hints were initially limited to just classes and interfaces, but was soon expanded to allow array and callable types too. PHP 7 extends this further by allowing scalar types like int, float, string and bool:
// Scalar type hint (PHP 7):
function getNextWeekday(int $date) { /*...*/ }
Type Checking Modes
PHP’s flexible type system is one of its most-useful features, allowing numeric strings to be used as integers and vice-versa. This tradition is continued in PHP 7 but now you have the option of enabling strict type enforcement like you’d see in other languages (such as Java or C#). This setting can be enabled using the declare construct.
Weak (“Coercive”) Type Checking
“Coercive” mode is the default type checking mode in PHP 7. This is identical to how previous versions of PHP handled scalar type hints for built-in functions. For example, take a look at the method signature for the floor function:
float floor ( float $value )
When you pass in numeric strings or integers PHP auto-converts them to a float automatically. This behavior has simply been extended to userland functions as well.
Here’s a table showing which scalar types are accepted in “Coercive” mode based on the declared type:
| Type declaration | int | float | string | bool | object |
|---|---|---|---|---|---|
| int | yes | yes* | yes† | yes | no |
| float | yes | yes | yes† | yes | no |
| string | yes | yes | yes | yes | yes‡ |
| bool | yes | yes | yes | yes | no |
* Only non-NaN floats between PHP_INT_MIN and PHP_INT_MAX accepted.
† If it’s a numeric string
‡ Only if object has a __toString() method
Strong (“Strict”) Type Checking
PHP 7 introduces a new “strict” mode which is enabled by placing declare(strict_types=1); at the top of your script like so:
<?php
declare(strict_types=1);
function welcome(string $name) {
echo 'Hello ' . $name;
}
welcome('World'); // Prints: Hello World
This declaration enables strict mode for all uses in the entire file, including built-in PHP function calls and return values (see next chapter). It does not affect any included files nor any other files which include it.
Strict mode essentially requires you to pass in exact types declared. If you don’t, a TypeError will be thrown. For example, in strict mode, you cannot use numeric strings when a float or int is expected (like you can in weak/coercive mode):
<?php
declare(strict_types=1);
function welcome(string $name) {
echo 'Hello ' . $name;
}
welcome(3);
// Fatal error: Uncaught TypeError: Argument 1 passed to welcome() must be of th\
e type string, integer given
There’s one exception to this rule though, which is that float declarations can accept int values:
<?php
declare(strict_types=1);
function add(float $a, float $b): float {
return $a + $b;
}
add(1, 2); // float(3)
| Type declaration | int | float | string | bool | object |
|---|---|---|---|---|---|
| int | yes | no | no | no | no |
| float | yes* | yes | no | no | no |
| string | no | no | yes | no | no |
| bool | no | no | no | yes | no |
* Allowed due to widening primitive conversion
Mixing Modes
Because the directive is set per-file, it’s entirely possible to mix modes in your application. For example, your strictly-checked app could use a weakly-checked library (or vice versa) without any issues or complications.
Backwards Compatibility
You may no longer create classes named int, float, string or bool as these would conflict with the new scalar type hints.