简体   繁体   中英

How to tell whether a variable is null or undefined in php

Is there a single function that can be created to tell whether a variable is NULL or undefined in PHP? I will pass the variable to the function (by reference if needed) but I won't know the name of the variable until runtime.

isset() and is_null() do not distinguish between NULL and undefined.
array_key_exists requires you to know the name of the variable as you're writing your code.
And I haven't found a way to determine the name of a variable without defining it.

Edit

I've also realized that passing a variable by reference automatically defines it.

Elaboration

Through the collection of these answers and comments I've determined that the short answer to my question is "No". Thank you for all the input.

Here are some details on why I needed this:

I've created a PHP function called LoadQuery() that pulls a particular SQL query from an array of queries and then prepares it for submission to MySQL. Most-importantly I scan the query for variables (like $UserID ) that I then replace with their values from the current scope. In creating this function I needed a way to determine if a variable had been declared, and was NULL, empty, or had a value. This is why I may not know the name of the given variable until runtime.

Using modified example from PHP - Differenciate an undefined variable from a null variable

we can differentiate it:

$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;

prints:

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

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

we can use array_key_exists(..., get_defined_vars()) and is_null(...) to detect both situations

You can't wrap this kind of logic in a function or method as any variable defined in a function signature will be implicitly "set". Try something like this (contains code smell)

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
}

In PHP typically variables that have not been set or that have been unset are considered null . The meaning of null is "no value". There is a distinct difference between "no value" and a value left blank. For instance, if a user submitted a form with foo=&bar=baz , $_GET['foo'] is set to the value of empty string "" , which is distinctly different from null which would be the value for any key other than 'foo' and 'bar' .

That all being said, you can find out if a variable was never set or unset , although they will always evaluate to true with is_null ( is_null is the negative of isset with the exception that it will throw notices if the value was never set).

One way is if you have the variable in an array of some sort:

echo array_key_exists( $variableName, $theArray ) ? 'variable was set, possibly to null' : 'variable was never set';

If you need to check a global variable, use the $GLOBALS array:

echo array_key_exists( $variableName, $GLOBALS ) ? 'variable exists in global scope' : 'this global variable doesn\'t exist';

The alternative method I've come up with for figuring out whether the variable was set is a bit more involved, and really unnecessary unless this is a feature that you absolutely have to have (in which case you should be able to build it without too much difficulty).

It relies on the fact that is_null triggers a notice when a variable hasn't been set. Add an error handler that converts errors into Exceptions , and use a try...catch... block to catch the exception that's thrown and set a flag in the catch statement. Just after the catch block execute your code that relies on this feature.

It's a dirty-nasty-hack if you ask me, and completely unnecessary, as null should be considered the same as an unset variable.

Essentially the answer is no. There is not a single function you can create that will tell whether a runtime variable is null or is undefined. (by 'runtime variable' I mean a variable who's name you don't yet know at the time of coding. See Elaboration in the question above).

Relevant Observations:

  • There's no way to retrieve the name of a variable at runtime without giving it a value and hence declaring it.
  • If you pass a variable by reference, instead of by value, you're automatically declaring it. So then in the function you can't go back and determine whether it was declared before you passed it.
  • You can use array_key_exists('variable_name', $GLOBALS) as @zzzzBov stated, to see if a variable has been declared, but only if you know the name of the variable at coding time.

Possible 'Dirty' Solutions

  • As @Phil (and @zzzzBov) explained you could use a messy trick of capturing error messages that would get thrown when you reference an undeclared variable.

  • I also considered a method where you: Make note of all the keys in $GLOBALS , then store a unique value in your target variable (recording it's original value first for later use). And then search $GLOBALS looking for that unique value to determine the name of the variable AND (by comparing with your earlier look at $GLOBALS ) determine if the variable existed before. But this also seems messy and unreliable.

您可以使用以下命令获取当前范围内已定义变量的数组:

get_defined_vars();

In PHP 5.2 or greater, I guess it is possible as follows:

// 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>';

Note: I did not have time to test this solution in all possible situations (I just use it in a plugin I developed), so everyone is invited to find a flaw here.

This only works with globally defined variables. Because of scoping it won't work with local variables in functions or with class properties, but of course it's only one line so you could just copy it into a function.

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

what about this?

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM