Nullsafe оператор в PHP 8: безопасный доступ через ?-> без лишних проверок

Nullsafe оператор в PHP 8: безопасный доступ через ?-> без лишних проверок

Nullsafe оператор в PHP 8: безопасный доступ через ?- без лишних проверок

Поисковый запрос, под который написана эта статья: nullsafe оператор PHP. Если вы часто пишете проверки вроде if ($user !== null) перед каждым обращением к объекту, оператор ?-> из PHP 8 может заметно упростить код.

Что такое nullsafe оператор в PHP

Nullsafe оператор — это оператор безопасного доступа к свойствам и методам объекта. Он записывается как ?-> и работает похоже на обычный ->, но с важным отличием: если слева оказался null, PHP не выбросит ошибку, а вернёт null.

Обычный код до PHP 8 часто выглядел так:

<?php

if ($user !== null && $user->profile !== null) {
    $city = $user->profile->city;
} else {
    $city = null;
}

С nullsafe оператором тот же код становится короче:

<?php

$city = $user?->profile?->city;

Если $user равен null, результатом будет null. Если $user->profile равен null, результат тоже будет null. Ошибки обращения к свойству у null не будет.

Простой практический пример

Представим интернет-магазин. У заказа может быть покупатель, у покупателя может быть адрес, а у адреса — город. Но не все данные обязательны.

<?php

class Address
{
    public function __construct(public string $city) {}
}

class Customer
{
    public function __construct(public ?Address $address) {}
}

class Order
{
    public function __construct(public ?Customer $customer) {}
}

$order = new Order(new Customer(null));

$city = $order->customer?->address?->city;

var_dump($city); // NULL

Обратите внимание: первый переход $order->customer выполнен через обычный оператор, потому что в нашем примере $order точно является объектом. А вот customer и address могут быть null, поэтому там используется ?->.

Когда использовать ?->

Nullsafe оператор особенно полезен, когда вы работаете с вложенными объектами, где некоторые уровни могут отсутствовать:

  • профиль пользователя может быть не заполнен;
  • заказ может быть без привязанной доставки;
  • у товара может отсутствовать категория;
  • метод репозитория может вернуть объект или null;
  • данные из API могут быть частично пустыми.
  • Например, метод поиска пользователя может вернуть User или null:

    <?php
    
    $user = $userRepository->findByEmail('admin@example.com');
    
    $name = $user?->getProfile()?->getDisplayName() ?? 'Гость';
    
    echo $name;
    

    Здесь хорошо сочетаются два инструмента: ?-> безопасно проходит по цепочке объектов, а ?? задаёт значение по умолчанию, если результат оказался null.

    Nullsafe оператор работает только на чтение

    Важное ограничение: через ?-> нельзя присваивать значение. Такой код вызовет ошибку:

    <?php
    
    $user?->profile?->city = 'Москва'; // Ошибка
    

    Почему так? Потому что если где-то в цепочке будет null, PHP не сможет понять, куда именно нужно выполнить присваивание. Для изменения данных лучше явно проверить объект:

    <?php
    
    if ($user !== null && $user->profile !== null) {
        $user->profile->city = 'Москва';
    }
    

    Вызов методов через nullsafe оператор

    Оператор ?-> можно использовать не только для свойств, но и для методов:

    <?php
    
    $email = $order->getCustomer()?->getEmail();
    

    Если getCustomer() вернёт null, метод getEmail() уже не будет вызван, а переменная $email получит значение null.

    Это удобно, но не стоит маскировать им важные ошибки. Если покупатель у заказа должен быть всегда, лучше не использовать ?->, а дать ошибке проявиться или выбросить исключение. Nullsafe оператор нужен для действительно необязательных данных.

    Комбинация с типами и возвращаемыми значениями

    В современном PHP полезно явно указывать nullable-типы. Например, знак вопроса перед типом означает, что метод может вернуть объект указанного класса или null:

    <?php
    
    class User
    {
        public function getProfile(): ?Profile
        {
            return $this->profile;
        }
    }
    
    $avatarUrl = $user->getProfile()?->getAvatarUrl() ?? '/img/default-avatar.png';
    

    Такой код хорошо читается: метод честно сообщает, что профиль может отсутствовать, а вызывающий код безопасно обрабатывает эту ситуацию.

    Типичные ошибки новичков

  • Использовать ?-> везде подряд. Если объект обязан существовать, обычный -> лучше покажет проблему в логике.
  • Забывать значение по умолчанию. Результатом цепочки может быть null, поэтому часто стоит добавить ??.
  • Пытаться присваивать через ?->. Nullsafe оператор предназначен для чтения и вызова методов, но не для записи.
  • Думать, что ?-> заменяет валидацию. Он только предотвращает ошибку доступа к null, но не проверяет корректность данных.
  • Рекомендации по использованию

    Используйте nullsafe оператор в PHP, когда отсутствие объекта является нормальной частью бизнес-логики. Например, у пользователя может не быть аватара, у товара может не быть скидки, у заказа может не быть комментария.

    Но если отсутствие объекта означает ошибку, лучше обработать это явно:

    <?php
    
    $customer = $order->getCustomer();
    
    if ($customer === null) {
        throw new RuntimeException('У заказа должен быть покупатель');
    }
    
    $email = $customer->getEmail();
    

    Такой подход делает код надёжнее: вы не прячете проблему, а фиксируете её в правильном месте.

    Мини-шпаргалка

    <?php
    
    // Безопасное чтение свойства
    $city = $user?->profile?->city;
    
    // Безопасный вызов метода
    $email = $user?->getProfile()?->getEmail();
    
    // Значение по умолчанию
    $name = $user?->getName() ?? 'Гость';
    
    // Так нельзя
    // $user?->profile = $profile;
    

    Если вы хотите не просто выучить отдельные операторы, а уверенно писать реальные сайты на PHP 8 с базами данных, авторизацией и практическими проектами, посмотрите практический курс по PHP и MySQL от основ до уверенной разработки. Он хорошо дополняет такие темы, как типы, ООП, работа с MySQL и безопасная обработка данных.

    Вывод

    Nullsafe оператор PHP ?-> делает код короче и безопаснее при работе с необязательными объектами. Он отлично подходит для чтения вложенных свойств и вызова методов, которые могут вернуть null. Главное — использовать его осознанно: не скрывать ошибки архитектуры и не забывать про значения по умолчанию через ??.

    Источник

    НЕТ КОММЕНТАРИЕВ

    Оставить комментарий