Enabling 'strict_types' globally in PHP 7
This is deliberately not possible, because the implementation adopted after an extremely long discussion of scalar type hints was this one: https://wiki.php.net/rfc/scalar_type_hints_v5
It introduces two modes for scalar type parameters, which both guarantee that the function receiving the parameters gets the types that it requires in its signature. However, it provides two modes for how calling code can achieve that:
- in mode 0, it automatically validates and casts certain scalar types (e.g.
int
parameter will convert'123'
to123
, but error on'hello'
) - in mode 1, it requires the caller to do that validation and casting before-hand, and rejects any parameter not of the correct type (e.g. both
'123'
and'hello'
are rejected for anint
parameter)
The choice of mode is per-file, and based on the caller of the function, because:
- the setting needs to affect built-in functions as well as user-defined ones
- all code that calls functions needs to be checked or updated to work correctly in mode 1, but most old code will run fine in mode 0
- with a global setting, you could only use libraries which had been tested with both modes, or the same mode you prefer
- files that don't declare their preferred mode need to continue to work similarly to PHP 5.x to allow existing code to run; that is only possible if the default is mode 0
From the point of view of someone writing a reusable library:
- regardless of the setting, your functions are guaranteed to receive the parameter types requested
- if you want to receive errors when you call functions with the wrong types, you can use mode 1 without forcing other applications and libraries to be on the same setting
- if you want to have the automatic checks and casts of mode 0, you can do that, but still interact with other libraries and applications which run in mode 1
- old libraries which were written before PHP 7.0 (or which needed to support both when it came out) will continue to work roughly as before, because the default mode 0 is similar to existing behaviour for built-in functions
It's therefore up to you to tell PHP which files have been written to use strict type mode, and which haven't; and the way to do this is using the declare
statement.
Where to add 'strict_types' for PHP7 in Symfony?
It's a per-file directive, so you must put it in every file.
References:
- http://php.net/manual/en/control-structures.declare.php
Strict mode in PHP
Kind of. You can activate the E_NOTICE
level in your error reporting. (List of constants here.)
Every instance of usage of an undeclared variable will throw an E_NOTICE
.
The E_STRICT
error level will also throw those notices, as well as other hints on how to optimize your code.
error_reporting(E_STRICT);
Terminating the script
If you are really serious, and want your script to terminate instead of just outputting a notice when encountering an undeclared variable, you could build a custom error handler.
A working example that handles only E_NOTICE
s with "Undefined variable" in them and passes everything else on to the default PHP error handler:
<?php
error_reporting(E_STRICT);
function terminate_missing_variables($errno, $errstr, $errfile, $errline)
{
if (($errno == E_NOTICE) and (strstr($errstr, "Undefined variable")))
die ("$errstr in $errfile line $errline");
return false; // Let the PHP error handler handle all the rest
}
$old_error_handler = set_error_handler("terminate_missing_variables");
echo $test; // Will throw custom error
xxxx(); // Will throw standard PHP error
?>
strict_types=1' does not seem to work in a function
"Strict types" mode only checks types at specific points in the code; it does not track everything that happens to the variable.
Specifically, it checks:
- the parameters given to the function, if type hints are included in the signature; here you are giving two
int
s to a function expecting twoint
s, so there is no error - the return value of the function, if a return type hint is included in the signature; here you have no type hint, but if you had a hint of
: int
, there would still be no error, because the result of$a + $b + $c
is indeed anint
.
Here are some examples that do give errors:
declare(strict_types=1);
$a = '1';
$b = '2';
function FunctionName(int $a, int $b)
{
return $a + $b;
}
echo FunctionName($a, $b);
// TypeError: Argument 1 passed to FunctionName() must be of the type integer, string given
Or for a return hint:
declare(strict_types=1);
$a = 1;
$b = 2;
function FunctionName(int $a, int $b): int
{
return $a . ' and ' . $b;
}
echo FunctionName($a, $b);
// TypeError: Return value of FunctionName() must be of the type integer, string returned
Note that in the second example, it is not the fact that we calculated $a . ' and ' . $b
that throws the error, it's the fact that we returned that string, but our promise was to return an integer. The following will not give an error:
declare(strict_types=1);
$a = 1;
$b = 2;
function FunctionName(int $a, int $b): int
{
return strlen( $a . ' and ' . $b );
}
echo FunctionName($a, $b);
// Outputs '7'
strict_types doesn't work when included
It is not currently possible to globally declare strict typing in PHP. From the manual:
It is possible to enable strict mode on a per-file basis
And
Strict typing applies to function calls made from within the file with strict typing enabled, not to the functions declared within that file. If a file without strict typing enabled makes a call to a function that was defined in a file with strict typing, the caller's preference (weak typing) will be respected, and the value will be coerced.
My guess is that, in part, this was to maintain compatibility amongst packages. What if you enable if globally and some package you're using requires strict typing to be off?
Until further notice you'll have to declare it in every file you're going to be using it.
PHP type hinting is being ignored, no TypeError exception is thrown
You need to add the strict_types
directive for type hinting to work properly
Quoting from PHP 7 New Features
To enable strict mode, a single declare directive must be placed at the top of the file. This means that the strictness of typing for scalars is configured on a per-file basis. This directive not only affects the type declarations of parameters, but also a function's return type (see return type declarations, built-in PHP functions, and functions from loaded extensions.
With that, you should do this.
<?php
declare(strict_types=1);
function get_option_foo() : int {
$val = get_option('foo'); // Returns a string that can be parsed as an int
return (bool) $val;
}
$foo = get_option_foo();
Try this once again, you will receive an Uncaught TypeError Exception
Related Topics
How to Add 24 Hours to a Unix Timestamp in PHP
Getting the Value of an Extra Pivot Table Column Laravel
Setting a PHP $_Session['Var'] Using Jquery
MySQL Password Expired. Can't Connect
Laravel Eloquent Update Just If Changes Have Been Made
How to Execute a Stored Procedure in PHP Using SQLsrv and "" Style Parameters
Explain $Ci =& Get_Instance();
How to Sort MySQL Fulltext Search Results by Relevancy
Leverage Browser Caching, How on Apache or .Htaccess
Load Blade Assets with Https in Laravel
After Array_Filter(), How to Reset the Keys to Go in Numerical Order Starting at 0
File_Get_Contents When Url Doesn't Exist
PHP Files Are Downloaded by Browser Instead of Processed by Local Dev Server (Mamp)