Sotomajor.org.ua - PHP development: В чем отличие isset() от is_null()?

Лабораторная работа. Цель: понять чем отличаются возможности двух функций. Приборы и материалы: интерпретатор PHP, текстовый редактор vi, мануал php :-) Результаты под катом.

corner icon

В чем отличие isset() от is_null()?

2008-07-29 08:57 // // Раздел:

Уверен, что многие, в том числе и довольно опытные, разработчики иногда натыкаются на какую-то мелочь, которая не до конца понятна. Из такой ситуации есть 2 выхода: забить или же разобраться. Я вот решил разобраться.

Предположения

Логично предположить, что функция is_null() наряду с другими функциями проверки типов is_bool(), is_float(), is_int(), is_string(), is_object(), is_array() и is_ resource() проверяет принадлежность переданного аргумента к типу NULL (да, да, это отдельный тип данных PHP). Тут всё в порядке - если мы передаем объект типа NULL, то мы получаем TRUE, если объект другого типа, то FALSE.

Подвох в другом. Is set можно перевести как "установлен ли". Вот и считают наивные PHP девелоперы, что если ранее в коде переменная встречалась слева от оператора присваивания, то isset() вернет для нее TRUE. Ну хотя бы пока она не будет уничтожена с помощью unset().

Теория

Чтобы не гадать - обратимся к мануалу. Там написано, что Переменная считается NULL если ей была присвоено значение NULL, ей еще не было присвоено какое-либо значение или она была удалена с помощью unset().

Теперь с функцией is_null() должно быть все понятно. Она проверяет является переменная значением типа NULL, а она может являться им только в 3х случаях. Не запутаешься.

А вот про isset() написано больше букаф: Determine whether a variable is set. If a variable has been unset with unset(), it will no longer be set. isset() will return FALSE if testing a variable that has been set to NULL. Also note that a NULL byte ("\0") is not equivalent to the PHP NULL constant.

Если вчитаться внимательно, то можно понять, что эта функция вернет FALSE для переменной, которая была установлена в NULL (или не установлена вовсе). Что и есть unexpected behaviour. Кроме того, она может принимать много параметров, но это уже не так важно.

Ход работы

Возьмем простой скриптик:
php:
<?php
error_reporting(E_NONE);
$b = null;
$c = 1;
unset($c);

echo 'isset($a): -> '.printBoolean(isset($a))."         ";
echo 'is_null($a): -> '.printBoolean(is_null($a))."     ";
echo '$a: -> '.printBoolean($a)."         ";
echo "\n\n";

echo 'isset($b): -> '.printBoolean(isset($b))."         ";
echo 'is_null($b): -> '.printBoolean(is_null($b))."     ";
echo '$b: -> '.printBoolean($b)."         ";
echo "\n\n";

echo 'isset($c): -> '.printBoolean(isset($c))."          ";
echo 'is_null($c): -> '.printBoolean(is_null($c))."    ";
echo '$c: -> '.printBoolean($c);
echo "\n\n";

function printBoolean($value) {
        if ($value) {
                return "TRUE";
        } else {
                return "FALSE";
        }
}

Запускаем и анализируем результаты.

php:
soto@y-deer:~/tmp> php test.php
isset($a): -> FALSE         is_null($a): -> TRUE     $a: -> FALSE
isset($b): -> FALSE         is_null($b): -> TRUE     $b: -> FALSE
isset($c): -> FALSE         is_null($c): -> TRUE      $c: -> FALSE

В левой колонке результат isset() для переменной, которая не была установлена, переменной, которой присвоен NULL и переменной, которая была уничтожена. В средней результат is_null(), а в правой приведение к типу boolean для тех же значений. Как видим, isset() и is_null() работают с точностью до наоборот.

Борьба противоположностей

Теперь можно с уверенностью сказать, что isset($a) = !is_null($a) для любого $a, а приведение к булевому типу для этих примеров работает как isset().

Однако, тот факт присвоено ли переменной значение (хотя бы даже и NULL) или нет все-таки играет роль. При передаче переменной, которая до этого не инициализировалась в is_null() будет сгенерировано сообщение типа PHP Notice: Undefined variable: a in /home/soto/tmp/test.php.

Вывод

Из всего вышесказанного можно сделать вывод, что isset() больше подходит для проверки входных данных, в инициализации которых мы не можем быть уверены, например чего-нибудь типа $_POST['foo']. А is_null() для проверки результатов возвращенных другими функциями и переменных, которые наверняка уже использовались в коде.

С другой стороны, для единообразия и читабельности кода, можно везде использовать issetl(). Название is_null() лучше отражает суть решаемой задачи, но заведомо генерировать PHP Notice даже если они и не выводятся - не очень хорошая идея.

В общем, это дело вкуса и привычки. С уверенностью можно сказать только одно - использовать в одном условии isset() и is_null() не имеет смысла.

  • — Написал: Сим · 2008-08-03 18:54 · #

    Не знаю, лично я предпичнтаю проверку на НУЛЛ.. приывычка…

  • — Написал: Сотомайор · 2008-08-03 19:06 · #

    Да, я понимаю. Понятно, что можно использовать и одну и другую функцию – дело вкуса. Я просто это написал потому что видел слишком много конструкций типа
    if (isset($x) && !is_null($x)).

  • — Написал: dypa · 2008-09-21 15:30 · #

    юзаю isset + empty

Добавить комментарий: