可锐资源网

技术资源分享平台,提供编程学习、网站建设、脚本开发教程

PHP 8.5 新增 #[\NoDiscard] 属性

在 PHP 中编写函数或方法时,我们通常会返回对调用者处理至关重要的值。这些返回值通常需要被使用。以下是一个简单的示例:

                                              function calculateSum(int $a, int $b): int 
{
return $a + $b;
}

$result = calculateSum(5, 10);

但有时,你可能会无意中忘记使用返回值,例如:

                                              // 忘记使用返回值
calculateSum(5, 10);

这看似不是什么大问题,但在大型应用程序中,如果你在处理某些操作时返回了错误或异常信息,而这些返回值被忽略,可能会导致难以察觉的 bug。这种 bug 往往在问题发生很久后才会显现,成为最令人头疼的问题之一。

PHP 8.5 引入的新 #[\NoDiscard] 属性正是为了解决这个问题。

什么是 #[\NoDiscard] 属性?

当函数或方法被标记为 #[\NoDiscard] 时,它向开发者表明该函数或方法的返回值应当被使用,而不应被忽略。如果开发者调用了一个标记为 #[\NoDiscard] 的函数但没有处理其返回值(例如未赋值、未使用或未进行类型转换),PHP 会抛出警告( E_WARNING E_USER_WARNING )。

警告信息可以包含自定义的说明,解释为什么返回值是重要的。

将返回值赋值给变量、在表达式中使用或进行类型转换(即使是赋值给一个临时变量)都算是“使用了”返回值。

以下是 #[\NoDiscard] 属性的定义:

                                              #[Attribute(Attribute::TARGET_METHOD|Attribute::TARGET_FUNCTION)]
final class NoDiscard
{
public readonly ?string $message;

public function __construct(?string $message = null) {}
}

使用 #[\NoDiscard] 属性

假设我们有一个函数返回一个状态码,指示操作是否成功。我们可以使用 #[\NoDiscard] 属性来确保返回值不被忽略。

                                              #[\NoDiscard("as the operation result is important")]
function performOperation(): int {
// 执行某些操作
return 1; // 1 表示成功,0 表示失败
}

// 调用函数但不使用返回值

performOperation();

// 调用函数并使用返回值
// 这不会触发警告
$status = performOperation();

如上例所示,如果我们调用 performOperation() 函数但不使用其返回值,PHP 会抛出警告,提示返回值需要被使用。在第二个调用中,我们将返回值赋值给 $status 变量,因此不会触发警告。

实际例子

以下是一个来自 RFC 的更实际的例子:

                                              #[\NoDiscard("as processing might fail for individual items")]
function bulk_process(array $items): array {
$results = [];

foreach ($items as $key => $item) {
if (\random_int(0, 9999) < 9999) {
// 模拟对 $item 进行处理,99.99% 的情况下成功
echo "Processing {$item}", PHP_EOL;
$error = null;
} else {
$error = new \Exception("Failed to process {$item}.");
}

$results[$key] = $error;
}

return $results;
}

$items = [ 'foo', 'bar', 'baz' ];


bulk_process($items);

// 没有警告,因为返回值被赋值使用了
$results = bulk_process($items);

在这个例子中, bulk_process 函数处理一个数组的项并返回结果数组。如果返回值未被使用,PHP 会抛出警告,提示返回值需要被处理。

显式转换为 void 或返回类型

如果你希望有意忽略返回值并避免警告,可以显式将返回值转换为 void (PHP 8.5 引入)或函数的返回类型。这在你明确想忽略返回值时非常有用。

以下是基于前例的示例:

                                              // 没有警告,因为使用了 (void) 转换
(void)bulk_process($items);

// 没有警告,因为返回值被类型转换使用了
// (但 (bool) 转换可能被 OPcache 优化掉)
(bool)bulk_process($items);

灵感来源

该功能受到 C++、Rust 等语言中类似属性的启发,这些属性有助于防止因忽略返回值而导致的 bug。

总结

#[\NoDiscard] 是 PHP 开发者的一项安全功能,有助于捕获忽略函数返回值可能导致的错误。尤其对于返回值表示操作成功或失败的函数,此功能特别有用。

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言