Nullsafe-оператор — это новый синтаксис в PHP 8.0, добавляющий в PHP возможность опциональной цепочки вызовов (optional chaining).
Nullsafe-оператор позволяет читать значения свойств и выстраивать цепочки возвращаемых методов значений, при этом он прерывает вычисление выражения (short-circuiting), если значение равно null , не вызывая при этом никаких ошибок.
Синтаксис похож на оператор доступа к свойствам/методам ( -> ), и по аналогии с nullable-типами nullsafe-оператор записывается как ?-> .
$foo?->bar?->baz;
Nullsafe-оператор тихо возвращает null , если выражение в левой части вычисляется как null .
class Customer {
public function getAddress(): ?Address {}
}
class Address {
public function getCountry(): string {}
}
$country = $customer->getAddress()->getCountry(); В приведенном выше фрагменте метод Customer::getAddress() может возвращать null; он возвращает значение null или объект класса Address .
Цепочка $customer->getAddress()->getCountry() не является безопасной к null, поскольку возвращаемое значение getAddress может быть null , и PHP выдаст ошибку при попытке вызвать метод getCountry() :
Fatal error: Uncaught Error: Call to a member function getCountry() on null in ...:...
Чтобы безопасно получить адрес, раньше приходилось проверять возвращаемые значения null перед дальнейшим обращением к ним.
$address = $customer->getAddress();
$country = $address ? $address->getCountry() : null; $address = $customer->getAddress();
if ($address) {
$country = $address->getCountry();
}
else {
$country = null;
} Nullsafe-оператор решает эту проблему путем краткого вычисления (short-circuiting) доступа к свойству/методу, немедленно возвращая null , если выражение слева от оператора равно null , и не выполняя оставшуюся часть выражения.
- $address = $customer->getAddress(); - $country = $address ? $address->getCountry() : null; + $country = $customer->getAddress()?->getCountry();
Nullsafe-оператор ?-> помогает избавиться от избыточных проверок с помощью isset() и тернарного оператора.
Nullsafe-оператор был добавлен в PHP 8.0 в промежутке между релизом alpha 3 и первой бета-версией, как раз тогда, когда PHP 8.0 достиг стадии заморозки функционала (feature freeze).
Только для чтения
Nullsafe-оператор предназначен только для чтения. С его помощью нельзя записывать или присваивать значения.
class Customer {
private ?Address $address;
public function getAddress(): ?Address {
return $this->address;
}
}
class Address {
public string $country;
}
$customer->getAddress()?->country = 'NL'; В этом примере делается попытка записи в свойство $country объекта Address . При использовании nullsafe-оператора это запрещено.
Fatal error: Can't use nullsafe operator in write context in ... on line ...
Цепочки вызовов
Nullsafe-операторы можно объединять в цепочки, и выполнение всего выражения будет прервано на первом же nullsafe-операторе, который встретит null.
$customer->getAddress()?->getCoordinates()->getLongitude()->format();
Такая цепочка вызовов безопасна к null. PHP прервет выполнение и немедленно вернет null , если какой-либо из nullsafe-операторов вернет null .
{code-ok} Nullsafe-оператор должен присутствовать на каждом шаге, где цепочка может быть прервана. Использование оператора ?-> не делает всю цепочку безопасной к null автоматически.
Вычисление слева направо
Nullsafe-оператор вычисляется слева направо. Что самое важное, он не имеет приоритета над другими вызовами функций или другими способами доступа, такими как доступ к элементам массива.
<?php
class Customer {
public function getAddress(): ?Address {}
}
class Address {
public function setCountry(string $country_code): void {}
}
$customer->getAddress()?->setCountry(GeoIP::getCountry()); Если метод Customer::getAddress возвращает валидный объект Address , будет выполнена функция GeoIP::getCountry() , а ее результат будет передан в вызов метода Address::setCountry() . Поскольку nullsafe-операторы вычисляются слева направо, метод GetIP::getCountry() никогда не будет вызван, если метод Customer::getAddress() вернет null .
Обратите внимание, что использование круглых скобок заставит выражение внутри них выполниться целиком, в отличие от стандартного порядка слева направо.
$customer->getAddress()?->setCountry((GeoIP::getAddress()?->getCountry()))
Если Customer::getAddress() возвращает значение, отличное от null , цепочка (GeoIP::getAddress()?->getCountry()) будет выполнена, а возвращаемое значение будет передано в вызов Address::setCountry() .
Без ссылок
Nullsafe-оператор нельзя использовать со ссылками.
$country = &$customer->getAddress()?->getCountry(); Fatal error: Cannot take reference of a nullsafe chain in ... on line ...
Влияние на обратную совместимость
Nullsafe-оператор представляет собой новый синтаксис и не может быть портирован на старые версии PHP.
Запуск кода, использующего nullsafe-оператор, приведет к ошибке синтаксического анализа (parse error):
Parse error: syntax error, unexpected '->' (T_OBJECT_OPERATOR) in ... on line ...
Комментарии (0)
Пока нет комментариев — будьте первым.