什么是永远 return 输入 PHP 8.1

What is never return type in PHP 8.1

PHP8.1介绍了neverreturn类型,是什么? nevervoid 有什么区别?

never 类型声明被引入用作 return 类型提示,用于从未有 return 语句的函数,既不隐式也不显式。并且必须通过抛出异常或使用 exit/die 函数退出来终止。

function redirect(string $uri): never 
{
    header('Location: ' . $uri);
    exit();
}

这里redirect被称为never-returning函数,因为:

1) 它没有明确定义的 return 语句。

function redirect(string $uri): never 
{
    exit();
    return 'something';
}

将产生:

PHP Fatal error: A never-returning function must not return

2) 它没有隐式定义的 return 语句。

function redirect(string $uri): never
{
    if (false) {
        header('Location: ' . $uri);
        exit();
    }
}

由于这里的条件永远不会满足,因此执行会跳过 if 语句 returning 隐式 NULL,这将导致:

PHP Fatal error: Uncaught TypeError: redirect(): never-returning function must not implicitly return

3) 它以 exit 函数结束它的执行

无效与永不

  • void 可以有 return;never 不能。
  • never 强制函数抛出或以 exit/die 终止,但 void 确实如此 不是。
  • never 是 PHP 类型系统中所有其他类型的子类型,包括 void(这允许 return 类型协变)。
  • 两者都不允许 return输入值。
  • 两者都不能用作参数或 属性 类型。
  • 两者都不能用作 return 类型的箭头函数。
  • 两者都只能作为独立类型使用(不允许并集或交集)。

何时选择 void 而不是 never,反之亦然?

当您希望 PHP 在函数调用后执行下一条语句时,您应该声明一个函数 return 类型 void。当您不希望 PHP 在该函数调用后执行下一条语句时,您应该声明它 never

使用 never (PHP 8.1) 你可以保护一个永远不会 return 的函数,例如如果你想确保创建的无限循环真的是无限的(从调用站点的角度来看):

<?php

function eternity(string $forEternity): never
{
    start:
    usleep(1000);
    goto start;
}

eternity('the future');
// <- we are here only after the next big-bang, not in this current universe.

这段代码超级简化,通常在这里忘记 goto 语句会触发错误。

无限循环通常也不需要保护 for(通常我们 从不 希望它们发生),但是 never 对于 die()exit()throw 异常的函数总是有用的。

同样,尽管标准控制流中不推荐这三种离开函数的方式(前两种甚至在某些 SAPI 中控制 运行 进程)。但最终(没有双关语意),可以让 IDE 和工具从代码中编码的 return 类型信息中看到函数永远不会 returns。这也包括使用此类工具或阅读代码的人。


使用 void (PHP 7.1) 你可以保证一个函数永远不会 return 是一个类型,包括底层类型 never (因为你只能使用 voidnever).

<?php

function back_from_eternity(string $forEternity): void
{
    usleep(100000); // not so long

    return $forEternity
}

$echo = back_from_eternity('soon');

允许 PHP 防止回声从永恒以及 reader 发现 $echo = (以及之后对该变量所做的任何事情)仍然需要通常的维护/调试/测试或开发。

  • 比较:

两者都有一个好处,即当它们被违反时会抛出异常,因此程序将永远不会按原样继续并呈现函数调用 returns void(所有双关语意)。

仍应考虑调用该函数的任何副作用。通常是关于他们的。