编程

PHP 8.2 新特性 — 允许将 null 和 false 作为单独的类型

1420 2022-11-15 09:07:31

PHP 8.0 添加了对联合类型的支持,使得将这两个类型或其他类型联合成为可能。8.0 中,falsenull 可以作为联合类型的一部分,但是不允许作为单独类型。

在 PHP 8.2 之前,nullfalse 只允许作为联合类型的一部分:

function foo(): string|null {}
function strpos(): int|false {}

在 PHP 8.0 和 8.1 中,尝试将 nullfalse 作为单独类型(而不是联合类型的一部分)会导致编译时致命错误:

function foo(): null {}
function bar(): false {}
Fatal error: Null can not be used as a standalone type in ... on line ...
Fatal error: False can not be used as a standalone type in ... on line ...

在 PHP 8.2 之后,允许将 nullfalse 作为单独类型使用。上面的代码片段在 PHP 8.2 以上的版本将不再会抛出错误。这使得 PHP 的类型系统更具表现力也更加完整,能够精确声明返回类型、参数类型和属性类型。

另外,PHP 8.2 将允许使用 null|false 这样的联合类型,会导致在老版本中出错。

PHP 函数和方法必须使用 PHPDoc 注释提供精确的类型信息,在函数中声明类型:

  class AnonUser extends User {
-     /**
-      * @return false
-      */
-     public function isAdmin(): bool {
+     public function isAdmin(): false {
          return false;
      }
  }

void 类型和 null 类型的差异

注意,声明 null 返回类型的函数,必须显式返回 null,否则函数会产生类型错误异常。没有显式返回值的,无论是没有返回声明,还是忽视返回值(return ;)的,可以继续使用 void 类型作为返回值。

以下的例子抛出了 TypeError 异常,因为它本应声明返回类型为 void,而不是 null

function foo(): null {}
foo();
TypeError: foo(): Return value must be of type null, none returned in ...:...

除非 null 是返回类型,使用 voidnever 返回类型一般是更为准备的做法。

null 类型的的可空性

如果声明了 null, 就不能使用 ?null 语法将其标志为 nullable,这样会导致冗余类型声明。PHP 会在编译时抛出错误:

function doNotMakeSense(): ?null {}
Fatal error: null cannot be marked as nullable in ... on line ...

向后兼容性影响

PHP 8.2 之前,不允许将 nullfalse 作为单独类型。PHP 8.2 后才开始允许,因此应该不会导致已有的老版本应用产生兼容性问题。

这一功能没办法使用补丁在老版本中实现。