DEV Community

Marinus van Velzen
Marinus van Velzen

Posted on

The way declare(strict_types=1) works in PHP

Readers of my previous article noticed that I used the strict_type declaration and asked me what it does. In this article I will explain what it does and why I started to love using it.

What does strict typing do

PHP has never really been a language with strict typing. You just had variables and you could put anything in it that you wanted, but we're slowly getting more and more type restrictions that we can use.

Type hinting in method parameters or class properties is very useful and it helps you catch type errors before you run your code. Class based type hinting has worked since PHP 5, but primitive hinting is rather new. When passing an unexpected type to a function, PHP will attempt to automatically cast the value to the expected type. If strict_types has been declared then PHP will throw an exception instead.

Using declare(strict_types=1) will tell PHP to throw type errors when you try to (accidentally) cast primitive values. Take a look at this example without the strict type declaration.

function dump(int $value): void  
{  
 var_dump($value);  
}  

dump('13.37');
dump(19.42);
Enter fullscreen mode Exit fullscreen mode

Running this script will result in the following output.

int(13)
int(19)
Enter fullscreen mode Exit fullscreen mode

You'll notice that our dump function expects integers even though we give it a string in one of our function calls. Your editor might call you out if you try to do this, but it's still valid PHP code.

How to enable strict types

Enabling strict typing for primitive values is as easy as adding a single statement to the top of your PHP files. Here is the example from above with the added declaration.

declare(strict_types=1)

function dump(int $value): void  
{  
 var_dump($value);  
}  

dump('13.37');
dump(19.42);
Enter fullscreen mode Exit fullscreen mode

Running this script with the declaration will result in the following error.

Fatal error: Uncaught TypeError: dump(): Argument #1 ($value) must be of type int, string given, called in /Users/rienvanvelzen/Desktop/demo.php on line 10 and defined in /Users/rienvanvelzen/Desktop/demo.php:5
Stack trace:
#0 /Users/rienvanvelzen/Desktop/demo.php(10): dump('13.37')
#1 {main}
  thrown in /Users/rienvanvelzen/Desktop/demo.php on line 5
Enter fullscreen mode Exit fullscreen mode

Using the strict_type declaration can help you catch bugs early on by restricting PHP to automatically cast primitive values. It may be a bit daunting when you start to use it, as you need to properly define everything from the start.

A (small) Caveat

There is one thing that you need to keep in mind when using the strict_type declaration. It only works for the file that the declaration is placed in. Meaning that when you use a class, which has the strict_type declaration, it can still result in PHP casting primitive value. So keep that in mind when you want to start using this!

Discussion (5)

Collapse
mindplay profile image
Rasmus Schultz

It only works for the file that the declaration is placed in. Meaning that when you use a class, which has the strict_type declaration, it can still result in PHP casting primitive value.

This isn't quite accurate, or at least not the full story.

What strict types enable is type-checking of calls from the file that declares it - even when you call out to other scripts that don't declare it.

Conversely, enabling strict type-checking in your script does not enforce it on other scripts.

What this means in practice, is that library authors can't enforce strict type-checking on calling code - so they can't safely design for the assumption that strict type-checking will happen. Whereas consumers of libraries can't be sure that all library code supports strict types - since the calling script can't selectively enforce type-checks against specific libraries, you may even need to arbitrarily separate calls to different libraries into different files/classes.

It's a very strange and sort-of backwards feature. In most languages, the effects of options like these are localized - but in PHP it kind of spreads out and affects the behavior of code you're calling.

I suspect this design decision stems from the overarching "sanity is optional" philosophy of PHP. 😏

Collapse
rocksheep profile image
Marinus van Velzen Author

This is what I meant with that section of the code, but I couldn't word it right. I'll rewrite it when I'm back from work.

Collapse
joelbonetr profile image
JoelBonetR

Probably it will be some sort of option to make the whole app strict (being false by default, of course 😂😂)

Collapse
motz795 profile image
MOATAZ795

Thank you very much, easy and interesting explanation

Collapse
sharakpl profile image
Sharak