?? возвращает значение слева, если оно существует и не равно null, иначе значение справа: $name = $_GET['name'] ?? 'Guest';. В отличие от прямого чтения ключа, он никогда не выдаёт предупреждений, когда переменной или ключа массива нет.
При первом запуске строки запроса нет, поэтому используются оба значения по умолчанию. Нажмите на ссылку во вкладке Page, и скрипт выполнится снова с заполненным $_GET. Чтение $_GET["name"] без ?? при первом запуске в обычной конфигурации PHP напечатало бы Warning: Undefined array key "name". Подробнее о данных запроса на странице про _POST.
?? это короткая проверка isset()
$a ?? $b означает ровно isset($a) ? $a : $b. Это работает с переменными, ключами массивов любой глубины и свойствами объектов и без жалоб останавливается на первом недостающем звене.
Проверка та же, что выполняет isset, поэтому ключ, который существует со значением null, тоже получает значение по умолчанию.
Цепочка ?? для нескольких источников
?? правоассоциативен, и цепочка может быть сколь угодно длинной. PHP возвращает первый операнд, который задан и не равен null.
??= присваивает, только если там null
$a ??= $b сохраняет $b в $a, только когда $a не задано или равно null. Это самый короткий способ заполнить значения по умолчанию или вычислить что-то один раз и переиспользовать.
Правая часть ??= вычисляется, только когда присваивание происходит, поэтому computing 4 появляется один раз.
?? и ?: (короткий тернарный)
?? проверяет на null. ?: проверяет на истинность. Для значений вроде 0, "" и "0" они дают разные ответы:
Количество "0" это настоящие данные: ?? их сохраняет, ?: заменяет. Сам по себе ?: выдал бы предупреждение об отсутствующем ключе, поэтому в блоке он обёрнут как ($inputs[$key] ?? null) ?: .... Про сам ?: рассказано на странице о тернарном операторе.
Nullsafe-оператор ?->
?-> это та же идея для объектов, появившаяся в PHP 8. Если объект слева равен null, вся цепочка останавливается и возвращает null, а не выбрасывает Error вроде Call to a member function getAddress() on null. Поставьте ?? в конце для значения по умолчанию.
Пользователь 2 существует, но адреса у него нет, а пользователя 3 нет вовсе. Оба доходят до значения по умолчанию ?? "unknown" без ошибки.
Частая ошибка: у ?? низкий приоритет
?? связывает слабее, чем . и арифметические операторы. Поэтому в "Count: " . $count ?? 0 PHP сначала собирает строку "Count: " . $count, которая никогда не бывает null, и значение по умолчанию не используется.
Оборачивайте выражение с ?? в скобки всякий раз, когда оно стоит внутри более крупного выражения.
Часто задаваемые вопросы
Что означает ?? в PHP?
?? это оператор объединения с null. $a ?? $b возвращает $a, если оно существует и не равно null, иначе $b. Это короткая запись isset($a) ? $a : $b, и она не выдаёт предупреждения, когда $a или ключ массива не определены.
Чем ?? отличается от ?: в PHP?
?? берёт запасное значение, только когда левая часть равна null или не задана, поэтому 0 ?? 5 даёт 0, а '' ?? 'x' даёт ''. ?: берёт запасное значение всякий раз, когда левая часть ложна, поэтому 0 ?: 5 даёт 5. Кроме того, ?: предупреждает о неопределённых переменных и ключах, а ?? нет.
Что делает ??= в PHP?
$a ??= $b присваивает $b переменной $a, только если $a равно null или не задано; иначе $a не меняется. Это короткая запись $a = $a ?? $b;, она появилась в PHP 7.4.
Что такое nullsafe-оператор ?-> в PHP?
$obj?->method() вызывает метод, только когда $obj не равно null; если оно null, вся цепочка возвращает null вместо ошибки. Вместе с ?? получается значение по умолчанию: $user?->getAddress()?->city ?? 'unknown'. Оператор появился в PHP 8.0.