- 严格模式的声明 必须 放在文件的顶部。
- 严格模式不仅作用于函数参数的类型声明,也作用于函数的返回值类型。
声明 PHP 文件作为严格模式的一个好事是,实际上只适用于当前文件。这确保了这个文件是严格类型,但是他没有影响到整个项目中的其他文件。这允许你一步一步的迁移非严格模式的代码。
使用提示类型没有 strict_types 可能导致微妙的错误。
严格类型之前,int x 意味着 x must have a value coercible to an int。
- a float (example: 13.1459 -> 13)
- a bool (example: true -> 1)
- a null (example: null -> 0)
- a string with leading digits (example: “15 Trees” -> 15)
设置严格模式后,you tell the engine that int x means x must only be an int proper, no type coercion allowed。
谁给更关心 strict_type
这行?is more for the reader than for the writer. Why? Bacause it will explicitly tell the reader:
The types in this current scope are treated strictly.
对比
代码语言:javascript复制<?php
function add(int $a, int $b): int
{
return $a $b;
}
var_dump(add(1.0, 2.0));
运行输出 int(3)
。
<?php
declare(strict_types=1);
function add(int $a, int $b): int
{
return $a $b;
}
var_dump(add(1.0, 2.0));
运行输出:
代码语言:javascript复制PHP Fatal error: Uncaught TypeError: Argument 1 passed to add() must be of the type int, float given, ...
声明位置
必须在脚本最前。不能写在脚本的中间,如下写法是错误的:
代码语言:javascript复制<?php
function add(int $a, int $b): int
{
return $a $b;
}
declare(strict_types=1);
var_dump(add(1.0, 2.0));
运行后报错:
代码语言:javascript复制PHP Fatal error: strict_types declaration must be the very first statement in the script in ...
不得使用 block mode 进行声明:
代码语言:javascript复制<?php
declare(strict_types=1) {
var_dump(1);
}
运行后报错:
代码语言:javascript复制PHP Fatal error: strict_types declaration must not use block mode in ...
多文件场景
例子 1
A.php
<?php
// 严格模式
declare(strict_types=1);
function add(int $a, int $b): int
{
return $a $b;
}
B.php
<?php
// 非严格模式
require 'A.php';
// 违反了 A 的定义
var_dump(add(1.0, 2.0));
运行
代码语言:javascript复制php B.php
int(3)
例子 2
A.php
<?php
// 非严格模式
function add(int $a, int $b): int
{
return $a $b;
}
B.php
<?php
// 严格模式
declare(strict_types=1);
require 'A.php';
// 违反了 A 的定义
var_dump(add(1.0, 2.0));
运行
代码语言:javascript复制php B.php
PHP Fatal error: Uncaught TypeError: Argument 1 passed to add() must be of the type int, float given, called in ...
小结
- 函数定义时的严格模式,行为并不会出现什么不同。
- 函数执行时的,严格模式会出现差异。
declare(strict_types=1);
的声明本身在 A.php 文件中完成。被 B.php 文件 require,而 B.php 并没有定义严格模式,那么执行 require 的 B.php 文件不会变成严格模式。
总结
只有在写 declare 的文件的执行部分才会执行严格模式,该文件中调用的其它函数(其它文件中的函数)也会被影响。
若果想完全使用严格模式,比较简单的方法是在所有 php 文件都写上 declare(strict_types=1);
。
工具
推荐自动格式化工具:symplify/easy-coding-standard。
References
- 关于 declare(strict_types=1) 的有效范围 | segmentfault
- Strict Types in PHP | medium
- Scalar type declarations | php
- Strict typing | php
– EOF –
- # php