Музыка

понедельник, 7 февраля 2011 г.

Шпаргалка для PHP: FALSE, NULL и значения, с ними связанные

В PHP значения FALSE и NULL и связанные с ними значения отличаются от того, как это обычно в других языках и имеют свои неочевидные особенности.
В статье рассмотрены эти особенности.
Для новичков это может быть полезно для видимости полной картины, для опытных читателей — обновить в памяти, если какой-то ньюанс вылетел из головы.






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


В соответствии с документацией PHP следующие значения равны FALSE после приведения в тип boolean:
  • само булевское значение FALSE
  • integer 0
  • float 0.0
  • пустой массив (array) – array().
  • an object with zero member variables (только в PHP 4, в статье не рассматривается)
  • специальное значение NULL (включая неустановленные переменные)
  • impleXML objects (в данной статье не рассматривается)
Это значит, что если такие значения, передаются в условие:
if (…) echo1”; else echo0”;
то будет выведена строка "0".

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

Например:


if (@$undefVar) { …}


Но использовать @ стоит только в крайних случаях, когда вы хорошо подумали и других подходящих вариантов нет. См. функцию 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 соответствовали различные елементы в массиве, можно использовать следующий подход. Опишем функцию:

function index($var) { if ($var === NULL) return 'NULL'; return 'V' . $var; }

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

$arr[index('')]='value for empty string '; $arr[index(NULL)]='value for NULL';

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


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


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


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

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



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


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


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

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

Из таблицы можно сделать некоторые приятные выводы:
1. Если мы знаем, что у нас используются только строки, то мы их можем спокойно сравнивать и не беспокоиться, что "" (пустая строка) будет равна "0".
2. Массивы никогда не равны строкам, целым и действительным числам.

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




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


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



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

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

if (array_key_exists('var', get_defined_vars()) ) { echo "var is defined"; // $var is assigned NULL } else { echo "var is NOT defined"; // $var is not defined or unset($var) was called }

Выводы


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

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

Тестирование проводилось на PHP 5.3.1.

Дополнительные ссылки


Комментариев нет:

Отправить комментарий