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:

Allowed types, coercive mode
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):

This throws an error in strict 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:

Scope widening example
<?php
declare(strict_types=1);

function add(float $a, float $b): float {
    return $a + $b;
}

add(1, 2); // float(3)
Allowed types, strict mode
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.

Further Reading