Reputation: 124768
I need to check if value is defined as anything, including null. isset
treats null values as undefined and returns false
. Take the following as an example:
$foo = null;
if(isset($foo)) // returns false
if(isset($bar)) // returns false
if(isset($foo) || is_null($foo)) // returns true
if(isset($bar) || is_null($bar)) // returns true, raises a notice
Note that $bar
is undefined.
I need to find a condition that satisfies the following:
if(something($bar)) // returns false;
if(something($foo)) // returns true;
Any ideas?
Upvotes: 115
Views: 84743
Reputation: 16793
If you are dealing with object properties which might have a value of NULL you can use: property_exists()
instead of isset()
<?php
class myClass {
public $mine;
private $xpto;
static protected $test;
function test() {
var_dump(property_exists($this, 'xpto')); //true
}
}
var_dump(property_exists('myClass', 'mine')); //true
var_dump(property_exists(new myClass, 'mine')); //true
var_dump(property_exists('myClass', 'xpto')); //true, as of PHP 5.3.0
var_dump(property_exists('myClass', 'bar')); //false
var_dump(property_exists('myClass', 'test')); //true, as of PHP 5.3.0
myClass::test();
?>
As opposed with isset(), property_exists() returns TRUE even if the property has the value NULL.
Upvotes: 35
Reputation: 1162
In my case I had the following code:
class SomeClass {
private $cachedInstance;
public instance()
{
if (! isset($this->cachedInstance)) {
$this->cachedInstance = GetCachedInstanceFromDb(); // long operation, that could return Null if the record not found
}
return $this->cachedInstance;
}
}
And it failed in a way that GetCachedInstanceFromDb()
got called multiple times if it returned null. All because isset()
would return false even if the property was explicitly set to Null.
So, I had to do the following changes:
Declare the property with initial value set to False;
Use strict (type-safe) comparison when checking for the current variable value;
class SomeClass {
private $cachedInstance = false; // #1
public instance()
{
if ($this->cachedInstance === false) { // #2
$this->cachedInstance = GetCachedInstanceFromDb();
}
return $this->cachedInstance;
}
}
Upvotes: 0
Reputation: 345
I found this topic when I was looking for a solution for an array. to check for the presence of an array element that contains NULL, this construction helped me
$arr= [];
$foo = 'foo';
$arr[$foo]= NULL;
if (array_key_exists('bar', $arr)) {}; // Should evaluate to FALSE
if (array_key_exists('foo', $arr)) {}; // Should evaluate to TRUE
if (array_key_exists($foo, $arr)) {}; // Should evaluate to TRUE
Upvotes: 9
Reputation: 4102
At risk of being downvoted, I wouldn't even bother - clearly PHP wanted you to logically think of NULL and Undef as the same. I just ran with it - I created a function:
bool isEmpty(& $davar);
that checks for isset (handles both null and undef), "", and array(). Note that this is purposefully not dealing with falseness; just empty. The & 'reference-izer' allows the variable to be passed even though undefined without an error message, and if you check for isset and return false first, your next checks against "" and array() can be made without error.
The next function takes advantage of this function and is used where you would use
$davar || some-default.
and that is:
mixed defaultForEmpty(& $daVar, $default);
which just has the condition:
if (isEmpty($daVar))
return $default;
else
return $daVar;
BTW, these work with object references, array indexes, $_GET, $_POST, etc..
Upvotes: -1
Reputation: 1081
I have found that compact
is a function that ignores unset variables but does act on ones set to null
, so when you have a large local symbol table I would imagine you can get a more efficient solution over checking array_key_exists('foo', get_defined_vars())
by using array_key_exists('foo', compact('foo'))
:
$foo = null;
echo isset($foo) ? 'true' : 'false'; // false
echo array_key_exists('foo', compact('foo')) ? 'true' : 'false'; // true
echo isset($bar) ? 'true' : 'false'; // false
echo array_key_exists('bar', compact('bar')) ? 'true' : 'false'; // false
Update
As of PHP 7.3 compact() will give a notice for unset values, so unfortunately this alternative is no longer valid.
compact() now issues an E_NOTICE level error if a given string refers to an unset variable. Formerly, such strings have been silently skipped.
Upvotes: 6
Reputation: 4640
The following code written as PHP extension is equivalent to array_key_exists($name, get_defined_vars()) (thanks to Henrik and Hannes).
// get_defined_vars()
// https://github.com/php/php-src/blob/master/Zend/zend_builtin_functions.c#L1777
// array_key_exists
// https://github.com/php/php-src/blob/master/ext/standard/array.c#L4393
PHP_FUNCTION(is_defined_var)
{
char *name;
int name_len;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
return;
}
if (!EG(active_symbol_table)) {
zend_rebuild_symbol_table(TSRMLS_C);
}
if (zend_symtable_exists(EG(active_symbol_table), name, name_len + 1)) {
RETURN_TRUE;
}
}
Upvotes: 1
Reputation: 17836
Here some silly workaround using xdebug. ;-)
function is_declared($name) {
ob_start();
xdebug_debug_zval($name);
$content = ob_get_clean();
return !empty($content);
}
$foo = null;
var_dump(is_declared('foo')); // -> true
$bla = 'bla';
var_dump(is_declared('bla')); // -> true
var_dump(is_declared('bar')); // -> false
Upvotes: 0
Reputation: 19441
IIRC, you can use get_defined_vars()
for this:
$foo = NULL;
$vars = get_defined_vars();
if (array_key_exists('bar', $vars)) {}; // Should evaluate to FALSE
if (array_key_exists('foo', $vars)) {}; // Should evaluate to TRUE
Upvotes: 104
Reputation: 15780
is_null($bar)
returns true, since it has no values at all. Alternatively, you can use:
if(isset($bar) && is_null($bar)) // returns false
to check if $bar
is defined and will only return true if:
$bar = null;
if(isset($bar) && is_null($bar)) // returns true
Upvotes: -3
Reputation: 7750
See Best way to test for a variable's existence in PHP; isset() is clearly broken
if( array_key_exists('foo', $GLOBALS) && is_null($foo)) // true & true => true
if( array_key_exists('bar', $GLOBALS) && is_null($bar)) // false & => false
Upvotes: 17