PHP 8.0: Оператор Null-safe

Безопасный вызов методов

Представленный в PHP 8 оператор nullsafe (?->)позволяет вам вызывать методы объекта или получать доступ к свойствам объекта в цепочке связанных объектов, где объект в цепочке потенциально может быть null. Его синтаксис аналогичен оператору доступа к свойству/методу (->).

$foo?->bar?->baz;

Оператор null safe по умолчанию возвращает null, если выражение в левой части оценивается как null.

class Customer {
    public function getAddress(): ?Address {}
}
class Address {
    public function getCountry(): string {}
}

$country = $customer->getAddress()->getCountry();

В приведенном выше фрагменте возвращаемое значение метода Customer::getAddress() является nullable и он может вернуть null или объект класса Address.

Цепочка $customer->getAddress()->getCountry() не является "null safe", поскольку возвращаемое значение 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;
}

Оператор null-safe решает эту проблему, замыкая доступ к свойству\методу и немедленно возвращает null, если левая часть оператора равна null, не выполняя остальную часть выражения.

// $address = $customer->getAddress();
// $country = $address ? $address->getCountry() : null;

$country = $customer->getAddress()?->getCountry(); 

Оператор ?-> null-safe может помочь сократить излишние проверки isset() и использование тернарного оператора.

Read-Only (Только для чтения)

Оператор null-safe предназначен только для чтения. Из него нельзя записывать/присваивать значения.

class Customer {
    private ?Address $address;

    public function getAddress(): ?Address {
        return $this->address;
    }
}

class Address {
    public string $country;
}

$customer->getAddress()?->country = 'NL';

Этот фрагмент пытается записать в свойство $country объекта Address. Это недопустимо при использовании оператора null-safe.

atal error: Can't use nullsafe operator in write context in ... on line ...

Chaining (Цепочки)

Оператор null-safe может быть соединен в цепочку, и выражение в целом будет замыкаться с первым оператором null-safe, встретившим null.

$customer->getAddress()?->getCoordinates()->getLongitude()->format();

Эта цепочка вызовов является null-безопасной. PHP остановится и немедленно вернет null, если любой из null-safe операторов вернет null.

Оператор Null-safe должен присутствовать на каждом шаге, на котором цепочка может быть замкнута. Использование оператора ?-> не сделает всю цепочку null-safe.

Evaluated from left to right (Оценивание слева направо)

Оператор null-safe выполняется слева направо. Самое главное, что он не определяет приоритет других вызовов функций или других моделей доступа, таких как доступ к массиву.

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(). Поскольку операторы null-safe оцениваются слева направо, метод GetIP::getCountry() никогда не будет вызван, если метод Customer::getAddress() вернет null.

$customer->getAddress()?->setCountry((GeoIP::getAddress()?->getCountry()))

Если Customer::getAddress() возвращает значение, отличное от null, будет выполнена цепочка (GeoIP::getAddress()?->getCountry()), и возвращаемое значение будет передано в вызов Address::setCountry().

No References (Ссылки отсутствуют)

Оператор null-safe не может быть использован со ссылками.

$country = &$customer->getAddress()?->getCountry();
Fatal error: Cannot take reference of a nullsafe chain in ... on line ...

Backwards Compatibility Impact (Обратная совместимость)

Оператор Null-safe - это новый синтаксис, который не может быть перенесен в старые версии PHP. Запуск кода, использующего оператор null-safe, приведет к ошибке:

Parse error: syntax error, unexpected '->' (T_OBJECT_OPERATOR) in ... on line ...
Написать комментарий