如何在PHP中判断变量是否为null或未定义

11
有没有一个单一的函数可以告诉PHP变量是NULL还是未定义?我将把变量传递给函数(如果需要,通过引用),但在运行时我不知道变量的名称。
isset()和is_null()不能区分NULL和未定义。 array_key_exists需要您在编写代码时知道变量的名称。 而且我没有找到一种方法来确定变量的名称而不定义它。
编辑
我也意识到通过引用传递变量会自动定义它。
详细说明
通过这些答案和评论的收集,我已经确定了我的问题的简短答案是“否”。感谢所有的输入。
以下是我需要这个的一些细节:
我创建了一个名为LoadQuery()的PHP函数,从查询数组中提取特定的SQL查询,然后准备将其提交给MySQL。最重要的是,我扫描查询变量(如$UserID),然后用当前范围中的值替换它们。在创建此函数时,我需要一种确定变量是否已声明为空、NULL或具有值的方法。这就是为什么我可能直到运行时才知道给定变量的名称的原因。

是的,我需要知道它是哪一个。它是NULL还是未定义。 - Andrew
可以使用 get_last_error 等方法来进行极其卑劣的操作,但这只是一种理论上的练习,而不是我想在代码中看到的东西。我会说这听起来像是一件非常奇怪的事情,可能可以通过其他层次或设计更好地处理。你能给我们举个例子,你会如何使用这段代码? - Wrikken
我考虑иү‡е°†undefined variableй”™иҮҮжҚ•иҺ·дҢњдёғжњЂеђҺзљ„еЉһжі•гЂ‚иү™дёҒдё»ж„ЏдёҚй”™гЂ‚ - Andrew
1
@Phil:我甚至想到了更脏的方法,将get_last_errordebug_backtrace混合在一起... 但是,这是不应该需要的。除非这是一个纯学术问题,否则这里存在设计缺陷,我们应该探讨一下。 - Wrikken
1
@Wrikken 同意,我想看看这是打算如何使用的。 - Phil
显示剩余4条评论
8个回答

5

使用改编自PHP - 区分未定义的变量和null变量

我们可以进行区分:

$v1 = null;

echo (isset($v1) ? '$v1 set' : '$v1 not set') . PHP_EOL;
echo (is_null($v1) ? '$v1 null' : '$v1 not null') . PHP_EOL;
echo (empty($v1) ? '$v1 empty' : '$v1 not empty') . PHP_EOL;
echo (array_key_exists('v1', get_defined_vars()) ? '$v1 defined' : '$v1 not defined') . PHP_EOL;

echo PHP_EOL;
echo (isset($v2) ? '$v2 set' : '$v2 not set') . PHP_EOL;
echo (@is_null($v2) ? '$v2 null' : '$v2 not null') . PHP_EOL;
echo (empty($v2) ? '$v2 empty' : '$v2 not empty') . PHP_EOL;
echo (array_key_exists('v2', get_defined_vars()) ? '$v2 defined' : '$v2 not defined') . PHP_EOL;

打印:

$v1 not set
$v1 null
$v1 empty
$v1 defined

$v2 not set
$v2 null
$v2 empty
$v2 not defined

我们可以使用array_key_exists(..., get_defined_vars())is_null(...)来检测这两种情况。

@is_null($v2) 在 PHP 中,你如何称呼 @?我想了解更多。不过回答很好。 - Umer Abbas
1
@OmarAbbas 中的 @ 符号只是为了抑制警告。 - Iłya Bursov

3
基本上答案是否定的。你不能创建一个单一的函数来判断运行时变量是null还是undefined。(所谓的'运行时变量'是指在编码时你还不知道它的名称的变量。详见上面的阐述)
相关观察:
- 没有办法在运行时检索变量的名称,除非给它赋值并声明它。 - 如果你通过引用传递变量,而不是通过值,那么你自动声明了它。所以在函数中,你无法确定它在传递之前是否已经被声明。 - 你可以使用 array_key_exists('variable_name', $GLOBALS) 来查看变量是否已经被声明,但是仅当你在编码时知道变量的名称时才能使用。
可能的“脏”解决方案:
- 正如@Phil(和@zzzzBov)所解释的那样,你可以使用一个混乱的技巧来捕获当你引用未声明的变量时会抛出的错误消息。 - 我还考虑过一种方法:记录$GLOBALS中所有键的名称,然后在目标变量中存储一个唯一的值(先记录它的原始值以备后用)。然后搜索$GLOBALS,查找那个唯一的值,以确定变量的名称,并通过与你早先查看$GLOBALS的结果进行比较,确定变量是否存在。但这也似乎很混乱和不可靠。

2
在PHP中,通常未设置或已取消设置的变量被认为是nullnull的含义是“没有值”。 “没有值”和留空之间有明显的区别。例如,如果用户提交了一个带有foo=&bar=baz的表单,则$_GET ['foo']设置为空字符串的值"",这与null截然不同,后者将是除'foo''bar'之外的任何键的值。
话虽如此,您可以找出一个变量是否从未设置或unset,尽管它们始终会使用is_null计算为trueis_nullisset的否定,但有一个例外:如果该值从未设置,它会抛出提示)。
一种方法是,如果您在某些数组中有该变量:
echo array_key_exists( $variableName, $theArray ) ? 'variable was set, possibly to null' : 'variable was never set';

如果您需要检查全局变量,请使用$GLOBALS数组:
echo array_key_exists( $variableName, $GLOBALS ) ? 'variable exists in global scope' : 'this global variable doesn\'t exist';

我想到了一种替代方法来确定变量是否被设置,这种方法有点复杂,除非你绝对必须要使用此功能(在这种情况下,你应该能够轻松构建它),否则真的没有必要。
这种方法依赖于一个事实,即当一个变量未被设置时,is_null会触发一个提示。添加一个错误处理程序,将errors转换为Exceptions,并使用一个try...catch...块捕获抛出的异常并在catch语句中设置标志。在catch块之后执行依赖于此功能的代码。
如果你问我,这是一个肮脏的恶心的hack,完全没有必要,因为null应该被视为与unset变量相同。

PHP 中没有 finally。另外,你是个抄袭猫 ;) - Phil
@Phil,我在写这篇文章时没有看过你的答案,因为当我开始写的时候它们还没有发布。我的编辑是为了完成我的想法,当我完成所有内容后,我阅读了其他人所写的内容。我同意我们有类似的想法。感谢你对finally块的catch提醒。 - zzzzBov

2
您不能将这种逻辑封装在函数或方法中,因为在函数签名中定义的任何变量都会被隐式“设置”。尝试像这样做(包含代码异味):
function exception_error_handler($errno, $errstr, $errfile, $errline ) {
    throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
}
error_reporting(E_ALL);
set_error_handler("exception_error_handler");

try {
    if (null === $var) {
        // null your variable is, hmmm
    }
} catch (ErrorException $e) {
    // variable is undefined
}

1

您可以使用以下代码获取当前作用域中定义的变量数组:

get_defined_vars();

0
在 PHP 5.2 或更高版本中,我猜可以按以下方式实现:
// checking a variable (before and after it is defined)
$var_status1 = @is_defined( $variable, __LINE__, __FILE__ ); // don't put any additional code on this line
$variable = NULL;
$var_status2 = @is_defined( $variable, __LINE__, __FILE__ ); // don't put any additional code on this line

function is_defined( $var, $line, $file ) {
    $e = error_get_last();
    if ( $e !== NULL && $e['type'] === 8 && $e['line'] === $line && $e['file'] === $file  ) {
        return 'Undefined';
    } else {
        return 'Defined';
    }
}

echo $var_status1 . '<br>';
echo $var_status2 . '<br>';

注意:我没有时间在所有可能的情况下测试这个解决方案(我只是在我开发的一个插件中使用它),所以欢迎大家在这里找到漏洞。

-1

这个怎么样?

try {
    $undefined_var
} catch (Exception $ex) {
    $is_undefined = true;
}
if(empty($is_undefined)){ ... }

-1

这仅适用于全局定义的变量。由于作用域的原因,它无法与函数中的局部变量或类属性一起使用,但当然它只有一行,所以您可以将其复制到函数中。

function isNullOrUndefined($variable_name) {
  global $$variable_name;
  if (!isset($$variable_name) || is_null($$variable_name)) {
    return true;
  }
  return false;
}

$foo = "foo";
$bar = null;

isNullOrUndefined("foo") //false
isNullOrUndefined("bar") //true
isNullOrUndefined("baz") //true

很好,除了需要我在编码时知道变量的名称,而我不会知道。 - Andrew
@Andrew 你怎么可能不知道变量的名称呢?否则你怎么使用它呢? - Phil
@Dan Simon,你测试过这个吗?它不会起作用,因为issetis_null是彼此的否定 - zzzzBov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接