PHP strict_types 严格模式

2023-08-23 18:49:38 浏览数 (2)

  • 严格模式的声明 必须 放在文件的顶部。

  • 严格模式不仅作用于函数参数的类型声明,也作用于函数的返回值类型。

声明 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)

代码语言:javascript复制
<?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

代码语言:javascript复制
<?php
// 严格模式
declare(strict_types=1);
function add(int $a, int $b): int
{
  return $a   $b;
}

B.php

代码语言:javascript复制
<?php
// 非严格模式
require 'A.php';
// 违反了 A 的定义
var_dump(add(1.0, 2.0));

运行

代码语言:javascript复制
php B.php

int(3)

例子 2

A.php

代码语言:javascript复制
<?php
// 非严格模式
function add(int $a, int $b): int
{
  return $a   $b;
}

B.php

代码语言:javascript复制
<?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

0 人点赞