Laravel optional()如何工作?

Fre*_*rik 3 php laravel

创建新模型时,我尝试使用optional()帮助程序在设置值时分配值。但是,如果user未在此上下文中设置对象,则会收到此错误:"Undefined property: stdClass::$user"

$this->events()->create([
    'category_a' => optional($event)->categoryA,
    'category_b' => optional($event)->categoryB,
    'user' => optional($event->user)->accountId,
]);
Run Code Online (Sandbox Code Playgroud)

为了明确起见,$event始终设置了,但是可以包含不同的值。有时category_a设置,有时category_b设置。可选的帮助程序似乎可以解决问题。但是,当对象深于一个层次时,它将引发错误。

那么,如何optional使用一个以上级别的对象正确地与助手一起工作?

Sas*_*mAL 14

另外,请记住,在 PHP 8+ 中,您可以使用null 安全运算符来获得相同的行为和更清晰的外观:

// PHP 8+
$this->events()->create([
    'category_a' => $event?->categoryA,
    'category_b' => $event?->categoryB,
    'user' => $event->user?->accountId,
]);
Run Code Online (Sandbox Code Playgroud)

它也是可链接的并且可以与方法一起使用:

// before PHP 8
$country = null;
if ($session !== null) {
    $user = $session->user;
    if ($user !== null) {
        $address = $user->getAddress();
        if ($address !== null) {
            $country = $address->country;
        }
    }
}

// PHP 8+
$country = $session?->user?->getAddress()?->country;
Run Code Online (Sandbox Code Playgroud)

@pedro-x 的注释:请注意,optional()适用于null|false值,而?->仅适用于null值。他们不一样!注意细节以避免破坏代码。

  • 我反对这一点。请注意,`option()` 适用于 `null|false` 值,而 php `?` 仅适用于 null 值。他们不一样!注意细节以避免破坏代码。干杯 (5认同)

Asu*_*sur 5

optional()助手通常用于通过accesing化子性质或上的空对象的方法,例如产生避免错误:

致命错误:在null上调用成员函数foo()

文档所指定:

可选函数接受任何参数,并允许您访问该对象的属性或调用方法。如果给定对象为null,则属性和方法将返回null而不引起错误。

一个实际的例子

在您的代码中,您正在访问addressuser模型调用的关系:

return $user->address->street;
Run Code Online (Sandbox Code Playgroud)

如果您有可能$user->address是null并尝试检查street,这将返回一个致命错误,这就是发生的地方optional(),通过使用帮助程序,您可以明确地说$user->address 可能为null,因此不要向我显示错误案子:

return optional($user->address)->street;
Run Code Online (Sandbox Code Playgroud)

这样,您将获得null而不是致命错误。

在我看来,这使代码更具可读性,可能等同于$user->address ? $user->address->street : null,但是正如您所看到的,它更加冗长。

就您的情况而言,正如评论所述,可以选择嵌套optional()助手,但是如果您有多个级别,则不能保留。我建议您制作一个在内部链接帮助程序的函数,以便您的语法看起来像n_optional($event, ['user'])->accountId

希望这对您有所帮助。

  • 我接受了你的回答,因为它回答了我的问题。然而,我最终所做的是使用*空合并运算符*。`'user' => $event->user->accountId ?? 空,` (6认同)