Есть ли возможность?

В JS есть такая штука как Optional Chaining. Про эту фичу есть в заметке

JS/ES2020: Optional Chaining and Nullish Coalescing
На дворе 2020 год, а в ES2020 уже есть 2 долгожданные фичи, которые облегчат работу. Но самое интересное, что эти фичи уже точно можно использовать в продакшене. Давайте рассмотрим их с примерами и поймем профит. Во первых - эти фичи уже доступны в браузерах: Т.е. эти фичи вполне можно использоват…

Суть проста: мы можем обратиться к несуществующей ветви объекта и при этом не получить ошибку. А есть ли такая возможность в PHP? Более того, в пхп у нас есть не только объекты как экземпляры класса, но и такая структура данных как ассоциативный массив (по сути словарь в терминах того же python).

Если в PHP обратиться к несуществующей ветке объекта или словаря (ассоциативного массива), то будут два типа ошибок:

  • Notice в случае доступа к несуществующему полю у существующего
  • Warning в случае  доступа к несуществующему полю у несуществующего

Кто-то предлагает просто все это дело мьютить символом собака:

<?php declare(strict_types=1);

$a = [];
$r = @$a['b']['c']['d'];

// Без скрытия сообщений об ошибках
// Notice: Undefined index: b
// Warning: Trying to access array offset on value of type null
// Warning: Trying to access array offset on value of type null


#EOF#

В случае с объектом типа stdClass:

<?php declare(strict_types=1);

$a = (object)[];
$r = @$a->b->c->d;

// Без скрытия сообщений об ошибках
// Warning: Undefined property: stdClass::$a
// Warning: Attempt to read property 'b' on null
// Warning: Attempt to read property 'c' on null


#EOF#

Но скрытие ошибок не лучший вариант, более того, это не избавляет от срабатывания кастомных обработчиков ошибок.

Другой вариант - использовать isset. Прелесть оператора в том, что ему можно передать всю цепочку:

<?php


$r = isset($a['b']['c']['d']) ? $a['b']['c']['d'] : null;



#EOF#

И это не вызовет ошибок. Но запись все еще длинная. Самый лучший и верный вариант это использовать Nullish Coalescing (объединение с Null) оператор:

<?php declare(strict_types=1);


$r = $a['b']['c']['d'] ?? null;

$r = $a->b->c->d ?? null;



#EOF#

Коротко, без генерации ошибок. Не путать с краткой записью тернарного оператора ( ?: ), который делает логическую проверку, но не делает проверку на isset.  Более того, логическая проверка меняет поведение и результат будет иной. Так что самый верный вариант - это Nullish Coalescing оператор.

Использование Empty

В PHP есть еще одна встроенная функция - empty. Она точно так же как isset делает проверку на существование, но дополнительно еще делает проверку на пустое значение. Пустое значение это:

  • "" (пустая строка)
  • 0 (целое число)
  • 0.0 (число с плавающей точкой)
  • "0" (строка)
  • NULL
  • FALSE
  • array(), [] (пустой массив)

Это так же может быть удобно, если вам нужно еще дополнительно сделать проверку:

<?php

empty($a['b']['c']['d']);


#

В случае с isset и empty переменная может вообще не существовать изначально, точно так же как и с оператором Nullish Coalescing.

Вот такой вот простой лайфхак.