PHP 8.0: Null-safe operator
Null-safe operator is a new syntax in PHP 8.0, that providesoptional chaining feature to PHP.
The null-safe operator allowsreading the value of property and method return valuechaining, where the null-safe operatorshort-circuits the retrieval if the value isnull,without causing any errors.
The syntax is similar to the property/method access operator (->), and following thenullable type pattern, the null-safe operator is?->.
$foo?->bar?->baz;Null safe operatorsilently returnsnull if the expression to the left side evaluates tonull.
class Customer { public function getAddress(): ?Address {}}class Address { public function getCountry(): string {}}$country = $customer->getAddress()->getCountry();In the snippet above, theCustomer::getAddress() method return value is nullable; It can return anull value, or an object ofAddress class.
The$customer->getAddress()->getCountry() chain is not "null safe", because the return value ofgetAddress can benull, and PHP throws an error when it tries to callgetCountry() method:
Fatal error: Uncaught Error: Call to a member function getCountry() on null in ...:...To safely access the address, it was necessary to check thenull return values before further accessing the return value.
$address = $customer->getAddress();$country = $address ? $address->getCountry() : null;$address = $customer->getAddress();if ($address) { $country = $address->getCountry();}else { $country = null;}The null-safe operator solves this byshort-circuiting the property/method access, and returningnull immediately if the left side of the operator isnull, without executing the rest of the expression.
- $address = $customer->getAddress();- $country = $address ? $address->getCountry() : null;+ $country = $customer->getAddress()?->getCountry();The?-> null-safe operator can help reduce excessiveisset() andternary checks.
Null-safe operator was added to PHP 8.0 between alpha 3 release and first beta release, right around the time PHP 8.0reached its feature-freeze.
Read-Only
The null-safe operator is read-only. It cannot write/assign values from it.
class Customer { private ?Address $address; public function getAddress(): ?Address { return $this->address; }}class Address { public string $country;}$customer->getAddress()?->country = 'NL';This snippet attempts towrite to the$country property of theAddress object. This is not allowed with the null-safe operator.
Fatal error: Can't use nullsafe operator in write context in ... on line ...Chaining
The null-safe operator can be chained, and the expression as a whole will be short-circuited from the first null-safe operator that encounters null.
$customer->getAddress()?->getCoordinates()->getLongitude()->format();This chain of calls are null-safe. PHP will stop and immediately returnnull if any of the null-safe return operators evaluate tonull.
{code-ok} Null-safe operatormust be present at every step the chain can be short-circuited. Using the
?->operator will not make the whole chain null-safe.
Evaluated from left to right
The null-safe operator is evaluated from left to right. Most importantly, itdoes not prioritize other function calls or other access patterns such as array-access.
<?phpclass Customer { public function getAddress(): ?Address {}}class Address { public function setCountry(string $country_code): void {}}$customer->getAddress()?->setCountry(GeoIP::getCountry());If theCustomer::getAddress method returns a validAddress object, theGeoIP::getCountry() will be executed, and passed to theAddress::setCountry() method call. Because the null-safe operators are evaluated from left to right, theGetIP::getCountry() method will never be called if theCustomer::getAddress() method returnsnull.
Note that using braces will make the expression inside the braces execute altogether, as opposed to the left-to-write pattern.
$customer->getAddress()?->setCountry((GeoIP::getAddress()?->getCountry()))IfCustomer::getAddress() returns a value other thannull, the(GeoIP::getAddress()?->getCountry()) chain will be executed, and the return value will be passed to theAddress::setCountry() call.
No References
The null-safe operator cannot be used with references.
$country = &$customer->getAddress()?->getCountry();Fatal error: Cannot take reference of a nullsafe chain in ... on line ...Backwards Compatibility Impact
Null-safe operator is a new syntax, and cannot be back-ported to older PHP versions.
Running code that uses null-safe operator will raise a parse error:
Parse error: syntax error, unexpected '->' (T_OBJECT_OPERATOR) in ... on line ...