Strict typing vs. Weak typing in PHP
With PHP 5, the core team had introduced type declarations (also known as type-hinting) that allow functions to require that parameters are of a certain type at call time. If the given value is of the incorrect type, then an error is generated: in PHP 5, this will be a recoverable fatal error, while PHP 7 will throw a TypeError exception.
Type declarations can be specified by adding a type before function parameters like so.
function sum(int $a, int $b)
{
return $a + $b;
}
So, now, whenever the method sum
is called, PHP would expect to get the respective parameters of specified types. For instance, following,
var_dump(sum(3, 7)) // 10
This is fine and now you would expect that the following will throw some sort of error now that we’re using type-hinting…
var_dump(sum(3.5, 7.5))
But here is the catch! PHP won’t throw any error on this because by default, PHP will coerce values of the wrong type into the expected scalar type if possible. For instance, a function that is given a float
for a parameter that expects an integer
will get a variable of type integer
. In other words, PHP will try to “fallback” to the target type from the given type whenever it can. This is called “weak typing”.
So, the previous example will print the output without any hiccup.
var_dump(sum(3.5, 7.5)) // 10
^ ^
3 7
Even the string representation of these numbers will work fine. So, the following will also work.
var_dump(sum("3.5", 8)) // 11
PHP will try to coerce “3.5” to its integer value which is happen to be 3
in this case and process it further accordingly.
Strict typing
To check types strictly, PHP allow us to enable strict mode on a per-file basis. In strict mode, only a variable of the exact type of the type declaration will be accepted, or a TypeError will be thrown.
To enable strict mode, a declare statement is used with the strict_types
declaration like so.
declare(strict_types=1);
function sum(int $a, int $b)
{
return $a + $b;
}
try {
var_dump(sum(1, 2));
var_dump(sum("1.5", 3));
} catch (TypeError $e) {
echo 'Error: '.$e->getMessage();
}
// int(3)
// Error: Argument 1 passed to sum() must be of the type int, string given, called in [...][...] on line 11
As you can see, when giving a string value where the function is expecting an integer value, PHP will now throw a fatal error which was not possible in weak-typing.
Caveats
There is one thing to note here and that is even in strict typing, a function can be given integer when it’s expecting a float value. This is one exception in strict typing.
Apart from this, PHP doesn’t support aliases for scalar types. So, the following for example…
declare(strict_types=1);
function foo(boolean $bar) {
return $bar;
}
try {
var_dump(foo(true));
} catch (TypeError $e) {
echo 'Error: '.$e->getMessage();
}
…will throw the following error,
Error: Argument 1 passed to foo() must be an instance of boolean, bool given, called in [...][...] on line 10
To fix this, we need to use bool
instead of boolean
when declaring the type.
declare(strict_types=1);
function foo(bool $bar) {
return $bar;
}
try {
var_dump(foo(true));
} catch (TypeError $e) {
echo 'Error: '.$e->getMessage();
}
// bool(true)
And lastly, Enabling strict mode will not only affect the function type declarations but return type declarations as well.
Enabling strict mode globally?
If you want to enable strict mode globally, unfortunately, there isn’t a central configuration where you can do this. Instead, you need to add the declare(strict_types=1);
statement at the top of every file you want to enable strict mode on.
So, if you want to enable strict mode globally, you can do this by using tools like sed
, awk
or another tool of your choice to replace all <?php
with <?php declare(strict_types=1);
in your project directory as mentioned by Nikita Popov in this comment.
Like this article?
Buy me a coffee👋 Hi there! I'm Amit. I write articles about all things web development. You can become a sponsor on my blog to help me continue my writing journey and get your brand in front of thousands of eyes.