PHP中的安全导航操作符?

Den*_*nis 6 php

有没有办法用某种安全导航操作符编写以下语句?

echo $data->getMyObject() != null ? $data->getMyObject()->getName() : '';
Run Code Online (Sandbox Code Playgroud)

所以它看起来像这样:

echo $data->getMyObject()?->getName();
Run Code Online (Sandbox Code Playgroud)

Dan*_*ack 28

从 PHP 8 开始,您可以使用空安全运算符,该运算符与空合并运算符结合使用,可以编写如下代码:

echo $data->getMyObject()?->getName() ?? '';
Run Code Online (Sandbox Code Playgroud)

通过使用?->代替->运算符链被终止,结果将为空。

“查看对象内部”的运算符被视为链的一部分。

  • 数组访问 ([])
  • 属性访问 (->)
  • 空安全属性访问 (?->)
  • 静态属性访问 (::)
  • 方法调用 (->)
  • 空安全方法调用 (?->)
  • 静态方法调用 (::)

例如对于代码:

echo $data->getMyObject()?->getName() ?? '';
Run Code Online (Sandbox Code Playgroud)

如果 $data 为 null,则该代码等效于:

$string = $data?->getObject()->getName() . " after";
Run Code Online (Sandbox Code Playgroud)

由于字符串连接运算符不是“链”的一部分,因此不会短路。


Jso*_*owa 12

Nullsafe 运算符允许您链接调用,避免检查链的每个部分是否不为空(空变量的方法或属性)。

PHP 8.0

$city = $user?->getAddress()?->city
Run Code Online (Sandbox Code Playgroud)

PHP 8.0 之前

$city = null;
if($user !== null) {
    $address = $user->getAddress();
    if($address !== null) {
        $city = $address->city;
    }
}
Run Code Online (Sandbox Code Playgroud)

使用null coalescing operator(不适用于方法):

$city = null;
if($user !== null) {
    $city = $user->getAddress()->city ?? null;
}
Run Code Online (Sandbox Code Playgroud)

Nullsafe operator抑制错误:

警告:尝试在致命错误中读取 null 属性“city”:

未捕获的错误:在 null 上调用成员函数 getAddress()

但是它不适用于数组键:

$user['admin']?->getAddress()?->city //Warning: Trying to access array offset on value of type null

$user = [];
$user['admin']?->getAddress()?->city //Warning: Undefined array key "admin"
Run Code Online (Sandbox Code Playgroud)


dec*_*eze 9

不,那里没有.

解决这个问题的绝对最佳方法是设计对象,使它们始终返回特定类型的已知,良好,定义的值.

对于绝对不可能的情况,您必须这样做:

$foo = $data->getMyObject();
if ($foo) {
    echo $foo->getName();
}
Run Code Online (Sandbox Code Playgroud)

或者可能

echo ($foo = $data->getMyObject()) ? $foo->getName() : null;
Run Code Online (Sandbox Code Playgroud)

  • 自2014年12月以来,有一个针对“ nullsafe”运算符`?->`的RFC草案:https://wiki.php.net/rfc/nullsafe_calls。但这仍然是草案。 (3认同)