declare(strict_types=1)
In coercive mode PHP helps: the string '5' becomes the number 5 by itself. But sometimes that help hides a bug. If a number arrived as a string, it was most likely read from a form or a file and nobody converted it, while the program quietly goes on.
Back to the machine. In the last lesson it had an obliging attendant who changed the note '5' into a 5 coin. The line declare(strict_types=1); sends the attendant home: the slot takes only a coin of the right shape.
Such a line is a directive: an instruction to PHP on how to read this file. The directive strict_types=1 turns on strict mode: PHP does not convert arguments and demands the exact type.
<?php
declare(strict_types=1);
function area(float $side): float
{
return $side * $side;
}
echo area(1.5), "\n"; // 2.25
echo area(3), "\n"; // 9Let's go through the program step by step:
declare(strict_types=1);turns on strict mode for this file. The directive goes first, right after<?php.area(1.5)passes afloat, and the type matches the declared one.area(3)passes anint, and the call still works: a whole number for afloatparameter is the one allowance of strict mode.- The result
9.0is a fraction with no fractional part, soechoprints it as9.
What strict mode refuses
A string holding a number no longer gets through in strict mode:
echo area('3'), "\n"; // ✗Fatal error: Uncaught TypeError: area(): Argument #1 ($side) must be of type float, string givenHere is what happens to arguments for an int parameter in strict mode:
'4': aTypeError, although the string holds a number;2.0: aTypeError, although there is no fractional part;true: aTypeError;4: passes, because the type matches.
Strict mode applies to built-in functions too: in such a file strlen(123) also throws a TypeError.
Here the machine picture simplifies things. The strict machine still lets a whole 3 coin into the slot for fractions, an int into a float. There is no allowance the other way round: 2.0 will not get into an int parameter.
Where the directive applies
Bigger programs are made of several files, and the directive applies only in the file where it is written. The main rule: what matters is where the call stands, not where the function is declared.
- The function is declared in a file without the directive, and the call stands in a file with it: the arguments are checked strictly.
- The function is declared in a file with the directive, and the call stands in a file without it: PHP converts the arguments as usual.
- A function's result is checked by the mode of the file where the function is declared.
- The directive does not carry over to other files: each file has to state it again.
Interviewers often ask this: in which file must the directive stand for a call to be checked strictly? The answer: in the file where the call is written.
Why turn on strict mode
Most modern projects put the directive at the top of every file. The reasons:
- an error shows up where it appears: a string instead of a number stops the call instead of quietly turning into a number;
- editors and code analyzers rely on exact types and find bugs before the program runs;
- the code reads one way only: whatever type is declared is the type that arrives.
The rest of the course's examples have no directive, so you can see how PHP converts types. Turn it on in your own projects.
Common mistake
The directive was not put first:
<?php
echo 'start', "\n";
declare(strict_types=1); // ✗Fatal error: strict_types declaration must be the very first statement in the scriptPHP checks this before the run, so the file does not run at all, and not even start prints. The fix is to put the directive right after <?php, before any other code.
Key points
declare(strict_types=1);as the first statement of a file turns on strict mode: arguments are not converted.- In strict mode,
'4'and2.0for anintparameter give aTypeError, while anintfor afloatparameter passes. - Whether a call is strict is decided by the file where the call is written, not the file where the function is declared.