Лучший способ проверить наличие переменной в PHP; isset () явно не работает - PullRequest
183 голосов
/ 06 января 2009

Из isset() документов :

isset() will return FALSE if testing a variable that has been set to NULL.

По сути, isset() не проверяет, установлена ​​ли переменная вообще, но имеет ли она значение, отличное от NULL.

Учитывая это, каков наилучший способ проверить наличие переменной? Я пробовал что-то вроде:

if(isset($v) || @is_null($v))

(@ необходимо, чтобы избежать предупреждения, когда $v не установлен), но is_null() имеет проблему, аналогичную isset(): он возвращает TRUE для неустановленных переменных! Также представляется, что:

@($v === NULL)

работает точно так же, как @is_null($v), так что это тоже.

Как мы должны надежно проверять наличие переменной в PHP?


Редактировать: в PHP явно есть разница между неустановленными переменными и переменными, установленными на NULL:

<?php
$a = array('b' => NULL);
var_dump($a);

PHP показывает, что $a['b'] существует и имеет значение NULL. Если вы добавите:

var_dump(isset($a['b']));
var_dump(isset($a['c']));

вы можете увидеть неоднозначность, о которой я говорю, с функцией isset(). Вот вывод всех трех из этих var_dump()s:

array(1) {
  ["b"]=>
  NULL
}
bool(false)
bool(false)

Дальнейшее редактирование: две вещи.

Один, вариант использования. Массив превращается в данные оператора SQL UPDATE, где ключи массива - это столбцы таблицы, а значения массива - это значения, которые должны применяться к каждому столбцу. Любой из столбцов таблицы может содержать значение NULL, обозначаемое передачей значения NULL в массиве. Вам нужен способ различения между ключом массива, который не существует, и значением массива, установленным на NULL; в этом разница между отсутствием обновления значения столбца и обновлением значения столбца до NULL.

Во-вторых, Ответ Zoredache , array_key_exists() работает правильно, для моего случая использования выше и для любых глобальных переменных:

<?php
$a = NULL;
var_dump(array_key_exists('a', $GLOBALS));
var_dump(array_key_exists('b', $GLOBALS));

выходы:

bool(true)
bool(false)

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

(Единственный другой случай, о котором я могу подумать, касается свойств класса, для которого есть property_exists(), который, согласно его документам , работает аналогично array_key_exists() в том смысле, что он должным образом различает отсутствие установить и установить на NULL.)

Ответы [ 17 ]

1 голос
/ 07 января 2009

Попробуйте использовать

unset($v)

Кажется, единственное время, когда переменная не установлена, это когда она специально не установлена ​​($ v). Похоже, ваше значение слова «существование» отличается от определения PHP. NULL, безусловно, существует, это NULL.

1 голос
/ 07 января 2009

Если я запускаю следующее:

echo '<?php echo $foo; ?>' | php

Я получаю сообщение об ошибке:

PHP Notice:  Undefined variable: foo in /home/altern8/- on line 1

Если я запускаю следующее:

echo '<?php if ( isset($foo) ) { echo $foo; } ?>' | php

Я не получаю ошибку.

Если у меня есть переменная, которую нужно установить, я обычно делаю что-то вроде следующего.

$foo = isset($foo) ? $foo : null;

или

if ( ! isset($foo) ) $foo = null;

Таким образом, позже в этом скрипте я могу безопасно использовать $ foo и знать, что он «установлен» и что по умолчанию он равен нулю. Позже я могу if ( is_null($foo) ) { /* ... */ }, если мне нужно, и точно знать, что переменная существует, даже если она равна нулю.

Полная документация isset читает немного больше, чем просто то, что было изначально вставлено. Да, он возвращает false для переменной, которая была ранее установлена, но теперь имеет значение null, но также возвращает false, если переменная еще не установлена ​​(никогда), и для любой переменной, которая была помечена как неустановленная. Он также отмечает, что байт NULL ("\ 0") не считается нулевым и возвращает true.

Определить, установлена ​​ли переменная.

Если переменная была сброшена с unset (), он больше не будет установлен. isset () вернет FALSE, если тестирует переменная, которая была установлена ​​в NULL. Также обратите внимание, что байт NULL ("\ 0") не эквивалентен PHP NULL постоянная.

0 голосов
/ 22 мая 2014

Согласно руководству по PHP для функции empty (): «Определите, считается ли переменная пустой. Переменная считается пустой, ЕСЛИ ЭТО НЕ СУЩЕСТВУЕТ, или если ее значение равно ЛОЖЬ. Empty () не генерирует предупреждение, если переменная не существует. " (Мой акцент.) Это означает, что функция empty () должна квалифицироваться как «лучший способ проверить существование переменной в PHP», согласно заголовку Question.

Однако этого недостаточно, потому что функция empty () может быть одурачена переменной, которая существует и имеет значение NULL.

Я прерываю свой предыдущий ответ, чтобы представить что-то лучше, потому что он менее громоздок, чем мой первоначальный ответ (который следует за этим прерыванием, для сравнения).

  function undef($dnc) //do not care what we receive
  { $inf=ob_get_contents();             //get the content of the buffer
    ob_end_clean();                     //stop buffering outputs, and empty the buffer
    if($inf>"")                         //if test associated with the call to this function had an output
    { if(false!==strpos($inf, "Undef"); //if the word "Undefined" was part of the output
        return true;                    //tested variable is undefined
    }
    return false;                       //tested variable is not undefined
  }

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

  ob_start();                           //pass all output messages (including errors) to a buffer
  if(undef($testvar===null))            //in this case the variable being tested is $testvar

Вы можете следовать за этими двумя строками с помощью чего угодно, например, такого:

    echo("variable is undefined");
  else
    echo("variable exists, holding some value");

Я хотел поместить вызов ob_start () и ($ testvar === null) внутри функции и просто передать переменную в функцию, но она не работает. Даже если вы попытаетесь использовать функцию «передать по ссылке» переменной в функцию, переменная BECOMES определится, и тогда функция никогда не сможет обнаружить, что она ранее была неопределенной. То, что здесь представлено, - это компромисс между тем, что я хотел сделать, и тем, что на самом деле работает.

Из предыдущего следует, что существует другой способ всегда избегать появления сообщения об ошибке «Неопределенная переменная». (Предполагается, что предотвращение такого сообщения - вот почему вы хотите проверить, является ли переменная неопределенной.)

   function inst(&$v) { return; }  //receive any variable passed by reference; instantiates the undefined

Просто вызовите эту функцию, прежде чем что-то делать с вашим $ testvar:

   inst($testvar);                //The function doesn't affect any value of any already-existing variable

Значение переменной, которая была недавно создана, конечно же, равно нулю!

(Прерывание заканчивается)

Итак, после некоторого изучения и экспериментов вот что-то гарантированно сработает:

 function myHndlr($en, $es, $ef, $el)
 { global $er;
   $er = (substr($es, 0, 18) == "Undefined variable");
   return;
 }

 $er = false;
 if(empty($testvar))
 { set_error_handler("myHndlr");
   ($testvar === null);
   restore_error_handler();
 }
 if($er)  // will be 1 (true) if the tested variable was not defined.
 { ; //do whatever you think is appropriate to the undefined variable
 }

Объяснение: переменная $ er инициализируется значением по умолчанию "no error". «Функция-обработчик» определена. Если $ testvar (переменная, которую мы хотим знать независимо от того, является ли она неопределенной), проходит предварительный тест функции empty (), то мы проводим более тщательный тест. Мы вызываем функцию set_error_handler () для использования ранее определенной функции-обработчика. Затем мы делаем простое сравнение идентичности с использованием $ testvar, КОТОРОЕ ЕСЛИ НЕ ОПРЕДЕЛЕННОЕ БУДЕТ ИСПРАВИТЬ ОШИБКУ. Функция-обработчик фиксирует ошибку и специально проверяет, является ли причиной ошибки тот факт, что переменная не определена. Результат помещается в переменную информации об ошибках $ er, которую мы можем позже протестировать, чтобы сделать все, что захотим, в результате узнавая наверняка, был ли определен $ testvar. Поскольку нам нужна только функция-обработчик для этой ограниченной цели, мы восстанавливаем исходную функцию обработки ошибок. Функция myHndlr должна быть объявлена ​​только один раз; другой код может быть скопирован в любое подходящее место для $ testvar или любой другой переменной, которую мы хотим проверить таким образом.

0 голосов
/ 07 января 2009

Я должен сказать, что за все мои годы программирования на PHP я никогда не сталкивался с проблемой, когда isset() возвращает false для пустой переменной. OTOH, у меня возникли проблемы с ошибкой isset() в пустой записи массива - но array_key_exists() в этом случае работает правильно.

Для сравнения, Icon явно определяет неиспользуемую переменную как возвращающую &null, поэтому вы используете тест is-null в Icon, чтобы также проверить наличие неустановленной переменной. Это делает вещи проще. С другой стороны, Visual BASIC имеет несколько состояний для переменной, которая не имеет значения (Null, Empty, Nothing, ...), и вам часто приходится проверять наличие более одного из них. Это, как известно, источник ошибок.

0 голосов
/ 29 мая 2015

Я думаю, что единственное полное решение - это уведомления о сообщениях с

error_reporting(E_ALL); // Enables E_NOTICE

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

Включение уведомления об уведомлении может не быть хорошей альтернативой во всех ситуациях, но есть веские причины для его включения:

Почему я должен исправлять ошибки E_NOTICE?

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

0 голосов
/ 01 февраля 2017

Единственный способ узнать, определена ли переменная в текущей области ($GLOBALS не заслуживает доверия), это array_key_exists( 'var_name', get_defined_vars() ).

0 голосов
/ 08 марта 2011

Я предпочитаю использовать не пустой как лучший метод для проверки существования переменной, которая а) существует, и б) не является нулевым.

if (!empty($variable)) do_something();
...