28

Is there any way to write the following statement using some kind of safe navigation operator?

echo $data->getMyObject() != null ? $data->getMyObject()->getName() : '';

So that it looks like this:

echo $data->getMyObject()?->getName();
mickmackusa
  • 43,625
  • 12
  • 83
  • 136
Dennis
  • 1,027
  • 1
  • 14
  • 30

4 Answers4

61

From PHP 8, you are able to use the null safe operator which combined with the null coalescing operator allows you to write code like:

echo $data->getMyObject()?->getName() ?? '';

By using ?-> instead of -> the chain of operators is terminated and the result will be null.

The operators that "look inside an object" are considered part of the chain.

  • Array access ([])
  • Property access (->)
  • Nullsafe property access (?->)
  • Static property access (::)
  • Method call (->)
  • Nullsafe method call (?->)
  • Static method call (::)

e.g. for the code:

$string = $data?->getObject()->getName() . " after";

if $data is null, that code would be equivalent to:

$string = null . " after";

As the string concatenation operator is not part of the 'chain' and so isn't short-circuited.

Danack
  • 24,939
  • 16
  • 90
  • 122
12

Nullsafe operator allows you to chain the calls avoiding checking whether every part of chain is not null (methods or properties of null variables).

PHP 8.0

$city = $user?->getAddress()?->city

Before PHP 8.0

$city = null;
if($user !== null) {
    $address = $user->getAddress();
    if($address !== null) {
        $city = $address->city;
    }
}

With null coalescing operator (it doesn't work with methods):

$city = null;
if($user !== null) {
    $city = $user->getAddress()->city ?? null;
}

Nullsafe operator suppresses errors:

Warning: Attempt to read property "city" on null in Fatal error:

Uncaught Error: Call to a member function getAddress() on null

However it doesn't work with array keys:

$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"
Jsowa
  • 9,104
  • 5
  • 56
  • 60
  • I think it's not optimal that it doesn't work with array keys. It's almost intuitive that it should... – Tim Nov 12 '21 at 19:11
7

No there is not.

The absolute best way to deal with this is to design your objects in a way that they always return a known, good, defined value of a specific type.

For situations where this is absolutely not possible, you'll have to do:

$foo = $data->getMyObject();
if ($foo) {
    echo $foo->getName();
}

or maybe

echo ($foo = $data->getMyObject()) ? $foo->getName() : null;
deceze
  • 510,633
  • 85
  • 743
  • 889
  • Okay. At least your second suggestion is a bit shorter than mine. – Dennis Sep 10 '12 at 13:04
  • 1
    I think that this would be a good addition to PHP language. After the ?? operator, something like the ?. operator of C#. So something like this could be written: `$stringVar = $datetimeobject?->format("Y-m-d")` – Moisés Márquez Mar 27 '18 at 07:29
  • 4
    There is an RFC draft for "nullsafe" operator `?->` since December 2014: https://wiki.php.net/rfc/nullsafe_calls. But it's still a draft. – G. Kashtanov Dec 26 '18 at 11:17
  • @dec you may want to edit this answer as PHP8 has the feature. – mickmackusa Nov 27 '20 at 22:21
1

For Laravel before PHP 8.0, you can use optional()

$city = optional(optional($user)->getAddress())->city
ALSP
  • 92
  • 1
  • 16