Проверка на null php


В работе с любыми данными то и дело требуется как-то обозначить их отсутствие. Новички зачастую для этой цели используют значение false, которое, по сути, является не отсутствием данных, а определённым значением типа boolean. Для того, чтобы как-то помечать неопределённость или отсутствие данных, существует специальное значение null. Про false, null и прочее уже немало сказано и добавить что-то оригинальное крайне сложно. Но гораздо сложнее бывает найти баг, вызванный неочевидным поведением этих штуковин. Поэтому, вдохновлённый одним таким багом, самым элегантным в моём послужном списке, я решил написать маленькую шпаргалку на эту тему.


Перегружать пост интересными, но довольно-таки бесполезными определениями из Википедии я не стану. Вместо этого перейду сразу к делу и приведу цитату со страницы php.net, посвящённой null:

Специальное значение NULL представляет собой переменную без значения. NULL — это единственно возможное значение типа null. Переменная считается null, если:

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

До этого момента всё кажется простым, но чтобы так оставалось и дальше, при работе с null нужно придерживаться определённых правил.

Математические операции с null

Во всех математических операциях null ведёт себя аналогично int(0):

  $a = null;  $a + 1; // int(1)  $a - 1; // int(-1)  $a * 1; // int(0)  1 / $a; // bool(false)   

Проверка переменной на null

Чтобы точно узнать, что переменная содержит null (то есть, ничего не содержит), нужно использовать либо специальную функцию is_null() либо тождественное сравнение ===, а любые другие способы не подойдут:

  // Правильная проверка переменной на null  $a = null;  is_null($a); // bool(true)  $a === null; // bool(true)   

Проверка null if-выражениях, а так же в функциях empty() и isset()

Тут переменные с null ведут себя абсолютно предсказуемо, как и любые другие ложные значения (которые в if-выражениях приводятся к false). Но нужно помнить, что это не гарантирует нам, что в переменной находится именно null:

Сравнение двух null

В PHP как гибкое, так и тождественное сравнение двух null всегда возвращает false, в отличие от многих других платформ, где сравнение двух неизвестностей возвращает так же неизвестность (то есть, null).

Поведение null при нетождественном сравнении с приведением типов данных

PHP разрешает сравнивать null-ы не только между собой, но и с другими типами данных. При этом не стоит забывать, что гибкое сравнение в php не является транзитивным, то есть, если два значения равны третьему по отдельности, не гарантирует их равенство между собой. Согласно таблицам приведения типов, гибкое сравнение null при помощи оператора == с разными значениями возвращает разные результаты:

Сравнение с null с помощью >, <, >=, <=, сравнение с отрицательными числами и другие заковырки

Не мне судить, насколько это является очевидным, но при сравнении с числами null всегда оказывается меньше них. Смотрите сами:

На вид ничего особенного, но из этого следует, что если в дело вмешивается null, может пройти бессмысленная, на первый взгляд, проверка:

Разное поведение null в PHP, SQL и JavaScript

А вот это, на мой взгляд, самое скверное. Реализуя логику работы с ячейками баз данных, в которых разрешено значение null, на разных этапах продвижения данных от сервера к пользователю (например, MySQL -> PHP -> JavaScript) поведение null может меняться.

Исследование null в JavaScript (а вместе с ним и загадочного undefined) заслуживает отдельной статьи. Главное отличие состоит в том, что, не смотря на приведение типов, null в JavaScript ничему не равен, кроме самого null и этого самого undefined, хотя в if-выражениях и срабатывает аналогично false. А при сравнении с числами он выдаёт ещё более забавные результаты, чем в PHP.

NULL в MySQL, к примеру, действует гораздо более прямолинейно. Он просто при любых действиях с null (даже при сравнении двух null) возвращает null. С его точки зрения, при любых действиях с неизвестностью в результате получится какая-то другая неизвестность 🙂

Простое правило при работе null, которое помогает избегать проблем

Вообще-то, не стоило читать этот пост. Держать в голове все эти нюансы, которые разные платформы трактуют по-разному, — неблагодарное занятие. Для того, чтобы избежать проблем с null нужно запомнить всего лишь одно правило:


Старайтесь не выполнять с null никаких лишних действий: не нужно его ни с чем сравнивать, складывать, сортировать. Там, где чисто теоретически переменная с null может просочиться в какие-то операторы, лучшим решением будет сперва проверить её функцией is_null().

mithrandir.ru

Codeigniter `where` и` or_where` Ошибка подключения сервера Apache FastCGI Ошибка PHP: невозможно изменить информацию заголовка – уже отправленные заголовки Попробовать Catch не может работать с require_once в PHP? К.


м и jQuery? Как установить MySQLi Очень высокая задержка в первом HTTP-запросе проекта CodeIgniter Prestashop: добавьте индивидуальный продукт в корзину PHP – как лучше определить, является ли текущий в&#.

E;тносительными путями в Symfony 2? Преобразование результатов регулярного выражения в нижний регистр Стандарт веб-платежей Paypal – возврат средств. Могут ли они быть сделаны через Api? Правило проверки пароля Laravel

ruphp.com

FALSE в If-выражениях

В соответствии с документацией PHP следующие значения равны FALSE после приведения в тип boolean:


  • само булевское значение FALSE
  • integer 0
  • float 0.0
  • пустая строка (string) («») и строка «0».
  • пустой массив (array) – array().
  • an object with zero member variables (только в PHP 4, в статье не рассматривается)
  • специальное значение NULL (включая неустановленные переменные)
  • SimpleXML objects (в данной статье не рассматривается)

Это значит, что если такие значения, передаются в условие:

то будет выведена строка «0».

Если значение переменной не установлено (unset), то еще и может выдаваться предупреждение. Напомним, предупреждение в условии можно убрать, написав перед переменной @.

Например:

Но использовать @ стоит только в крайних случаях, когда вы хорошо подумали и других подходящих вариантов нет. См. функцию isset().

Функция is_null() и языковые конструкции isset() и empty()


is_null() возвращает TRUE только для переменных, которым не присвоено никакого значения или которым присвоено значение NULL.

isset() возвращает один в один противоположные булевые значения в сравнении с is_null().

Если переменной не присвоено значение, то is_null() также выдает предупреждение «Undefined variable», в отличии от isset(), которая не выдает никаких предупреждение.

Напомним, для того, чтобы убрать значение переменной, можно использовать функцию unset(). Также с этой целью можно присвоить значение NULL, чтобы избежать предупреждений компилятора при попытке чтения значения переменной.

Обратите внимание, что в отличии от переменных для работы с константами необходимо использовать конструкцию defined().

С empty() все просто – возвращает TRUE для истинных значений, FALSE – для всех остальных, полностью в соответствии со списком выше, взятым из документации. Кстати, для тех кто будет экспериментировать самостоятельно, в empty() аргументом можно передать только переменную. При попытке передать константу компилятор выдает синтаксическую ошибку.

Индексация массивов

При работе с массивами все ложные значения будут обращаться к одному элементу.

Исключением являются только значения индексов пустой строки (») и NULL — для этих двух значений используется отдельное место в памяти.

Также значение пустого массива array(), как впрочем и любого другого массива, не может быть индексом массива – компилятор выдает предупреждение «Illegal offset type» и значение, соответствующее такому индексу, не устанавливается.


Для того, чтобы индексам пустой строки и NULL соответствовали различные елементы в массиве, можно использовать следующий подход. Опишем функцию:

Далее при установке значений мы получим отдельные индексы для пустой строки и значения NULL, точнее будем эмулировать различные индексы:

Индексы массивов — это отдельная тема. Приведу лишь пример того, что значение с целочисленным индексом $arr[555] совпадает со значением соответствующее строковыму индексу $arr[‘555’] в массиве.

Такие особенности прежде всего связаны с тем, что индексы массивов либо целые, либо строки. Более детальная информация может быть найдена в описании типа массива в руководстве php.

Строковое представление

Расмотрим строковое представление ложных констант.

Например при конкатенации значения преобразуются в следующие строки, приведенные в таблице ниже:

Значение Строка
FALSE (пустая строка)
0 0
0.0 0
«» (пустая строка)
«0» 0
array() Array
NULL (пустая строка)
@$undef (пустая строка)

Более подробно тема преобразования в строки описана на официальном сайте в параграфе Converting to string.

Операторы сравнения

Перейдем к операторам сравнения.

Все ложные значения, как и ожидалось, возвращают истину при сравнении со значением FALSE при помощи оператора «==».

Но не следует здесь расчитывать на транзитивность при сравнении ложных строковых констант между собой.

Приведем полную таблицу сравнения ложных значение (плюсом обозначены элементы таблицы, которые при сравнении с помощью оператора «!=» возвращают истинное значение:

!= FALSE 0 0.0 «» «0» array() NULL @$undef
FALSE
0 +
0.0 +
«» + +
«0» + + + +
array() + + + +
NULL +
@$undef +

$undef –переменная, которой не присваивалось значение

Из таблицы можно сделать некоторые приятные выводы:

1. Если мы знаем, что у нас используются только строки, то мы их можем спокойно сравнивать и не беспокоиться, что «» (пустая строка) будет равна «0».

2. Массивы никогда не равны строкам, целым и действительным числам.

Поскольку тип различных ложных констант разный, то для того, чтобы их отличать можно использовать пару операторов === и !==.

Оператор === возвращает ложное значение для всех пар ложных значений.

Истинное значение возвращает лишь для аргументов, одному из которых присвоено значение NULL, а второму не присвоено никакого значения.

Отличие переменных с NULL значением и неопределенных переменных

Оператор === позволяет различать все ложные значения, кроме как переменных с NULL-значением от переменных, которым значение не присваивалось.

Такие переменные можно отличить с помощью функции get_defined_vars().

Если нужно определить, было ли присвоено значение переменной $var, то для этого может быть использован следующий фрагмент код:

Выводы

Всегда нужно помнить, что в PHP два ложных значения могут быть не равны между собой, а переменные, которые, на первый взгляд, разные, могут оказаться одинаковыми при сравнении. Чтобы избежать таких сюрпризов, можно воспользоваться операторами === и !==.

При работе с массивами, во избежание сюрпризов, можно написать функцию конвертирования значений в гарантированно различные индексы. После этого к элементам массива обращаться только с ее помощью. Это может замедлить работу программы, но поможет избежать сюрпризов.

w1c.ru

For what I realized is that  is_null($var)  returns exactly the opposite of  isset($var) , except that is_null($var) throws a notice if $var hasn't been set yet.

the following will prove that:

<?php

$quirks = array(null, true, false, 0, 1, '', "", "unset");

foreach($quirks as $var) {
    if (
$var === "unset") unset($var);

    echo is_null($var) ? 1 : 0;
    echo isset(
$var) ? 1 : 0;
    echo
"n";
}

?>

this will print out something like:

10    // null
01    // true
01    // false
01    // 0
01    // 1
01    // ''
01    // ""
Notice:  Undefined variable: var in /srv/www/htdocs/sandbox/null/nulltest.php on line 8
10    // (unset)

For the major quirky types/values is_null($var) obviously always returns the opposite of isset($var), and the notice clearly points out the faulty line with the is_null() statement. You might want to examine the return value of those functions in detail, but since both are specified to return boolean types there should be no doubt.

A second look into the PHP specs tells that is_null() checks whether a value is null or not. So, you may pass any VALUE to it, eg. the result of a function.
isset() on the other hand is supposed to check for a VARIABLE's existence, which makes it a language construct rather than a function. Its sole porpuse lies in that checking. Passing anything else will result in an error.

Knowing that, allows us to draw the following unlikely conclusion:

isset() as a language construct is way faster, more reliable and powerful than is_null() and should be prefered over is_null(), except for when you're directly passing a function's result, which is considered bad programming practice anyways.

php.net


You May Also Like

About the Author: admind

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

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте как обрабатываются ваши данные комментариев.