空条件运算符是否总是在第一次空出现时中断?

Does null conditional operator always break on first null ocurrence?

具有 C# 背景,我在访问 class 属性(使用 Entity Framework 关系时)时总是使用 ?. 运算符。

例如,如果我使用它并且状态 class 为空,它将抛出异常,因为我试图从空对象中获取 属性。

var order = DB.Order.Find(1);

var status = order.status.text;

要解决这个问题,我可以这样做:

var address = order.status?.text ?? "No status";

?. 运算符将在第一个 null 处中断并跳过其余的访问。

我在 PHP 遇到过同样的情况,不得不这样做:

$order = Orders::find(1);
$status = $order->status->text;

如果状态为空,它会抛出相同的异常(试图从空对象中获取 属性)。

但后来我这样做了并且成功了:

$status = $order->status->text ?? "No status";

显然,如果 status 为空,PHP 将跳过 ->text 访问。

created a fiddle检查这是否不仅在我的环境中,令人惊讶的是它工作得很好!

<?php
$j = "Hello!";
echo $a->b->c->d->e ?? $a->b->c->d ?? $a->b->c ?? $a->b ?? $j;

<< "Hello!"

这真的是 PHP 中 ?? 运算符的预期行为吗?因为我没有看到文档中提到这个。

经过一些研究,我发现 PHP 7 中添加的空条件运算符 (??) 基本上是 isset() 函数的语法糖,就好像它被用在三元调用中。

echo isset($a->b->c) ? $a->b->c : "Hello!";

isset 函数的文档显示了一个尝试访问深层数组值的清晰示例:

<?php

$a = array ('test' => 1, 'hello' => NULL, 'pie' => array('a' => 'apple'));

// Checking deeper array values
var_dump(isset($a['pie']['a']));        // TRUE
var_dump(isset($a['pie']['b']));        // FALSE
var_dump(isset($a['cake']['a']['b']));  // FALSE

?>

当变量为 null 时,isset() 函数不会抛出 E_NOTICE,它只是跳过其余的访问。由于空合并运算符基本上在内部使用 isset(),因此在尝试访问空对象上的 属性 时也不会抛出异常。

Here is the link 到实施建议,它包含一个 link 到包含此运算符源代码的合并请求。