Операторы для null: ?? и ?:
Значение в программе есть не всегда. Переменную могли не задать, или в ней лежит null — «значения нет». Тогда нужна замена по умолчанию: «гость» вместо имени, пять вместо лимита.
Вернёмся к двум кассирам. Покупатель протягивает купон на скидку. Снисходительный кассир считает пустым любой купон, на котором ничего толком не написано: ноль, пустую строку. Строгий берёт скидку по умолчанию, только если купона нет совсем.
В PHP строгого кассира здесь зовут ??, а снисходительного — ?:.
<?php
$discount = null;
echo $discount ?? 5, "\n"; // 5
echo $coupon ?? 'none', "\n"; // none
$discount = 0;
echo $discount ?? 5, "\n"; // 0
echo $discount ?: 5, "\n"; // 5Давайте разберём программу по строкам:
$discount ?? 5печатает5: в$discountлежитnull.$coupon ?? 'none'печатаетnone: переменной$couponнет совсем, и PHP не выдаёт предупреждения.- После
$discount = 0выражение$discount ?? 5печатает0: ноль — настоящее значение, а неnull. $discount ?: 5печатает5: для?:ноль считается пустым.
Оператор ??
Оператор объединения с null записывают как $a ?? $b:
- если
$aзадана и не равнаnull, результат —$a; - иначе результат —
$b.
?? сначала проверяет, есть ли переменная, и только потом читает её. Поэтому на незаданной переменной он молчит, хотя обычное чтение $coupon дало бы Warning: Undefined variable $coupon.
Цепочка ??
Операторы ?? можно ставить друг за другом: $a ?? $b ?? 'x'. PHP проверяет слева направо и берёт первое значение, которое задано и не равно null. Если $a и $b равны null, результат — 'x'.
Оператор ??=
$limit ??= 20 записывает 20 в $limit, только если переменная не задана или равна null:
$limit = null;
$limit ??= 20;
$page = 0;
$page ??= 1;
echo $limit, ' ', $page, "\n"; // 20 0В $limit теперь 20, а $page остаётся 0: ноль задан и не равен null.
Оператор ?:
$a ?: $b берёт $b, когда $a превращается в false. Из значений, которые вы уже знаете, в false превращаются:
falseиnull;0и0.0;- пустая строка
''и строка'0'.
Это те же значения, которые (bool) превращает в false. Для ?: пустая строка в $name значит «имени нет», поэтому $name ?: 'guest' даёт guest.
В отличие от ??, оператор ?: читает переменную как обычно. Если её не задали, PHP выдаст предупреждение, как при любом чтении незаданной переменной.
Чем ?? отличается от ?:, часто спрашивают на собеседовании. Ответ:
??заменяет толькоnullи незаданную переменную, причём без предупреждения;?:заменяет всё, что превращается вfalse, включая0и'';?:читает переменную как обычно, и незаданная переменная даётWarning.
Здесь картинка с кассирами упрощает. Живой кассир спросит, что вы имели в виду, а ?: не спрашивает: для него ноль всегда пустота, даже если это честная цена в ноль рублей. Когда 0 или '' — допустимые значения, берите ??.
Частая ошибка
Имя по умолчанию подставляют через ?:, а переменную никто не задал:
echo $nickname ?: 'guest', "\n"; // ✗Warning: Undefined variable $nicknamePHP печатает предупреждение, а затем guest: ?: читает $nickname как обычную переменную, а её нет. Программа продолжает работу, но предупреждение говорит об ошибке в коде. Замените ?: на ??: $nickname ?? 'guest' печатает guest без предупреждения.
Главное
??подставляет правую часть, когда левой нет или в нейnull, и не выдаёт предупреждения.?:подставляет правую часть для всего, что превращается вfalse:0,'','0',null.$x ??= 20записывает20, только если$xне задана или равнаnull.- Когда ноль или пустая строка — допустимые значения, выбирайте
??.