null, isset и empty
Условие if ($x) спрашивает, истинно ли значение. Но иногда переменной $x в программе нет вовсе: ей не присвоили значение или ошиблись в её имени. Что тогда скажет условие?
<?php
if ($nickname) { // ✗
echo 'Hi, ', $nickname, "\n";
}
echo 'next', "\n";Warning: Undefined variable $nicknameПеременная $nickname нигде не получила значения. PHP выдаёт предупреждение, читает её как null, пропускает ветку и печатает next. Программа работает дальше, но предупреждение говорит об ошибке в коде, и оставлять его нельзя.
Представьте, что на развилке вы ищете табличку с названием города. Возможны три положения:
- таблички нет совсем — переменная не определена;
- табличка висит, но пустая — в переменной
null; - на табличке что-то написано — в переменной есть значение.
Для таких проверок в PHP есть три инструмента, и отвечают они на разные вопросы.
Три проверки
isset
isset($x) спрашивает: «табличка висит, и на ней что-то написано?» Ответ true, если переменная существует и её значение не null.
$city = 'Paris';
$phone = null;
var_dump(isset($city)); // bool(true)
var_dump(isset($phone)); // bool(false)
var_dump(isset($email)); // bool(false)Разберём по строкам:
- В
$cityлежит строка, поэтомуissetдаётtrue. - В
$phoneлежитnull, иissetдаётfalse. $emailне определена, иissetдаётfalseбез всякого предупреждения.
Почему нет предупреждения? isset — не функция, а языковая конструкция: часть самого языка, которая проверяет переменную сама, а не получает её значение, как функция. Поэтому отсутствующая переменная не вызывает у isset предупреждения.
Здесь аналогия расходится с PHP. На развилке пустую табличку видно сразу. Но isset не отличает её от отсутствующей: и для $phone = null, и для неопределённой переменной он даёт false.
empty
empty($x) спрашивает: «табличка пустая или её нет совсем?» Ответ true, если переменной нет или её значение ложное — из того же списка, что и в условии. empty($x) работает как !isset($x) || !$x.
$count = 0;
$title = 'News';
var_dump(empty($count)); // bool(true)
var_dump(empty($title)); // bool(false)
var_dump(empty($missing)); // bool(true)Разберём по строкам:
0— ложное значение, поэтомуempty($count)даётtrue, хотя переменная задана.- В
$titleнепустая строка, иemptyдаётfalse. $missingне определена:empty— тоже языковая конструкция, и она молча даётtrue.
is_null
is_null($x) спрашивает, пустая ли табличка, то есть равно ли значение именно null. Ответ true только для null. Для 0 и '' is_null даёт false, потому что это не отсутствие, а значения.
Но is_null — обычная функция. Чтобы передать ей значение, PHP сначала читает переменную и на отсутствующей выдаёт то же предупреждение, что и if:
Warning: Undefined variable $emailПосле предупреждения is_null($email) всё равно возвращает true: отсутствующую переменную PHP читает как null.
Сравним три проверки
Значение $x | isset($x) | empty($x) |
|---|---|---|
| переменной нет | false | true |
null | false | true |
0 или '' | true | true |
'Anna' | true | false |
Этот вопрос часто задают на собеседовании: «Чем отличаются isset, empty и is_null?» Ответ:
isset— переменная есть и не равнаnull, без предупреждений;empty— переменной нет или её значение ложное, тоже без предупреждений;is_null— значение именноnull; это функция, и на отсутствующей переменной она предупреждает.
Оператор ??
Как вы уже знаете, $a ?? $b даёт $a, если оно задано и не равно null, а иначе $b. Это isset в форме выражения: $name = $nickname ?? 'guest'; работает как isset($nickname) ? $nickname : 'guest' и тоже обходится без предупреждений.
Частая ошибка
Количество из формы пришло строкой '0', и его наличие проверили через empty:
$quantity = '0';
if (empty($quantity)) { // ✗
echo 'enter a quantity', "\n";
} else {
echo 'ordered: ', $quantity, "\n";
}Программа печатает enter a quantity, хотя человек ввёл ноль: '0' — ложное значение, и empty считает его пустым. Чтобы отличить «не заполнено» от нуля, проверяйте отсутствие и пустую строку отдельно: if (!isset($quantity) || $quantity === '').
Главное
isset($x)даётtrue, когда переменная есть и не равнаnull, и никогда не предупреждает.empty($x)даётtrueдля отсутствующей переменной и для любого ложного значения, включая0и'0'.is_null($x)проверяет толькоnull; это функция, и на неопределённой переменной она выдаёт предупреждение.$a ?? $b— этоissetв форме выражения.