views:

2604

answers:

8

From the isset() docs:

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

Basically, isset() doesn't check for whether the variable is set at all, but whether it's set to anything but NULL.

Given that, what's the best way to actually check for the existence of a variable? I tried something like:

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

(the @ is necessary to avoid the warning when $v is not set) but is_null() has a similar problem to isset(): it returns TRUE on unset variables! It also appears that:

@($v === NULL)

works exactly like @is_null($v), so that's out, too.

How are we supposed to reliably check for the existence of a variable in PHP?


Edit: there is clearly a difference in PHP between variables that are not set, and variables that are set to NULL:

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

PHP shows that $a['b'] exists, and has a NULL value. If you add:

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

you can see the ambiguity I'm talking about with the isset() function. Here's the output of all three of these var_dump()s:

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


Further edit: two things.

One, a use case. An array being turned into the data of an SQL UPDATE statement, where the array's keys are the table's columns, and the array's values are the values to be applied to each column. Any of the table's columns can hold a NULL value, signified by passing a NULL value in the array. You need a way to differentiate between an array key not existing, and an array's value being set to NULL; that's the difference between not updating the column's value and updating the column's value to NULL.

Second, Zoredache's answer, array_key_exists() works correctly, for my above use case and for any global variables:

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

outputs:

bool(true)
bool(false)

Since that properly handles just about everywhere I can see there being any ambiguity between variables that don't exist and variables that are set to NULL, I'm calling array_key_exists() the official easiest way in PHP to truly check for the existence of a variable.

(Only other case I can think of is for class properties, for which there's property_exists(), which, according to its docs, works similarly to array_key_exists() in that it properly distinguishes between not being set and being set to NULL.)

A: 

If it is null, it is not "set", is it? It does the right thing. It is checking for existence. Maybe I just don't understand why you would have to also check for null, you probably know a lot more about PHP than I do. Why would you expect is_null to return false on unset variables?

Ed Swangren
These aren't the same thing at all in PHP. See my edit.
chazomaticus
A: 

If I run the following:

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

I get an error:

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

If I run the following:

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

I do not get the error.

If I have a variable that should be set, I usually do something like the following.

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

or

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

That way, later in the script, I can safely use $foo and know that it "is set", and that it defaults to null. Later I can if ( is_null($foo) ) { /* ... */ } if I need to and know for certain that the variable exists, even if it is null.

The full isset documentation reads a little more than just what was initially pasted. Yes, it returns false for a variable that was previously set but is now null, but it also returns false if a variable has not yet been set (ever) and for any variable that has been marked as unset. It also notes that the NULL byte ("\0") is not considered null and will return true.

Determine whether a variable is set.

If a variable has been unset with unset(), it will no longer be set. isset() will return FALSE if testing a variable that has been set to NULL. Also note that a NULL byte ("\0") is not equivalent to the PHP NULL constant.

Beau Simensen
He got the docs off that link. Read the first sentence, second paragraph of the description section on the link you provided It is exactly what he quoted above.
Zoredache
This isn't a bad practice for simple scripts, but in complex (e.g. large OO) projects, it becomes infeasible. Also, as I said above, is_null() returns TRUE for variables that are not set, so there's really no reason to do what you're saying except to avoid a PHP warning.
chazomaticus
For well designed "large OO" projects, why would this be a problem at all? Why would you ever have $foo in a method body that may have not been set before its first usage?
Beau Simensen
Please see my use case edit in my question.
chazomaticus
+8  A: 

If the variable you are checking would be in the global scope you could do a array_key_exists('v', $GLOBALS)

Using the `isset($GLOBALS["v"]) may be a tempting, cleaner looking solution, but this still won't work i the global $v is null.

Zoredache
This doesn't help for the case when the global $v is NULL.
chazomaticus
Ah ha! NOW you're talkin'! How would you do that for, say, class properties?
chazomaticus
http://php.net/property_exists ?
Chad Birch
Awesome. Any chance you could edit your answer to make it clearer at first glance that array_key_exists() is real solution here? Might make it quicker/easier for future SOers.
chazomaticus
Lol. I thought of this method, and spendt 3 minutes testing it -- before I saw your answer. Oh well. +1 =)
gnud
As a variation, if the check needs to work for local scope variables as well, on can do a `$defined_vars = get_defined_vars();` and then test via `array_key_exists('v', $defined_vars);`.
Henrik Opel
A: 

I have to say in all my years of PHP programming, I have never encountered a problem with isset() returning false on a null variable. OTOH, I have encountered problems with isset() failing on a null array entry - but array_key_exists() works correctly in that case.

For some comparison, Icon explicitly defines an unused variable as returning &null so you use the is-null test in Icon to also check for an unset variable. This does make things easier. On the other hand, Visual BASIC has multiple states for a variable that doesn't have a value (Null, Empty, Nothing, ...), and you often have to check for more than one of them. This is known to be a source of bugs.

staticsan
A: 

Try using

unset($v)

It seems the only time a variable is not set is when it is specifically unset($v). It sounds like your meaning of 'existence' is different than PHP's definition. NULL is certainly existing, it is NULL.

Joe Philllips
I'm not sure what you mean. If you have an array, with one element 'a', you don't have to unset() element 'b' for element 'b' not to exist in PHP, it just doesn't exist. Same thing with e.g. global variables, which you can think of as elements of the $GLOBALS array.
chazomaticus
But I agree that a variable with a NULL value does in fact exist.
chazomaticus
+2  A: 

Object properties can be checked for existence by property_exists

Example from a unit test:

function testPropertiesExist()
{
    $sl =& $this->system_log;
    $props = array('log_id',
                   'type',
                   'message',
                   'username',
                   'ip_address',
                   'date_added');

    foreach($props as $prop) {
        $this->assertTrue(property_exists($sl, $prop),
                           "Property <{$prop}> exists");
    }
}
+2  A: 

You can use the compact language construct to test for the existence of a null variable. Variables that do not exist will not turn up in the result, while null values will show.

$x = null;
$y = 'y';

$r = compact('x', 'y', 'z');
print_r($r);

// Output:
// Array ( 
//  [x] => 
//  [y] => y 
// ) 

In the case of your example:

if (compact('v')) {
   // True if $v exists, even when null. 
   // False on var $v; without assignment and when $v does not exist.
}

Of course for variables in global scope you can also use array_key_exists().

B.t.w. personally I would avoid situations like the plague where there is a semantic difference between a variable not existing and the variable having a null value. PHP and most other languages just does not think there is.

Matijs
A: 

Explaining NULL, logically thinking

I guess the obvious answer to all of this is... Don't initialise your variables as NULL, initalise them as something relevant to what they are intended to become.

Treat NULL properly

NULL should be treated as "non-existant value", which is the meaning of NULL. The variable can't be classed as existing to PHP because it hasn't been told what type of entity it is trying to be. It may aswell not exist, so PHP just says "Fine, it doesn't because there's no point to it anyway and NULL is my way of saying this".

An argument

Let's argue now. "But NULL is like saying 0 or FALSE or ''.

Wrong, 0-FALSE-'' are all still classed as empty values, but they ARE specified as some type of value or pre-determined answer to a question. FALSE is the answer to yes or no,'' is the answer to the title someone submitted, and 0 is the answer to quantity or time etc. They ARE set as some type of answer/result which makes them valid as being set.

NULL is just no answer what so ever, it doesn't tell us yes or no and it doesn't tell us the time and it doesn't tell us a blank string got submitted. That's the basic logic in understanding NULL.

Summary

It's not about creating wacky functions to get around the problem, it's just changing the way your brain looks at NULL. If it's NULL, assume it's not set as anything. If you are pre-defining variables then pre-define them as 0, FALSE or "" depending on the type of use you intend for them.

Feel free to quote this. It's off the top of my logical head :)

greatbigmassive