Various ways of evaluating a variable

NYPHP - PHundamentals

Evaluating a variable, whether it is generated by a script or input by a user, turns out to be somewhat more complicated than one might suspect. The focus here will be on determining whether the variable contains something; if it does, then additional tests will normally be necessary to determine whether it contains something meaningful.

Among the techniques that might be considered are the following:

1.  if (!$var)
2.  if (empty($var))
3.  if ($var=='')
4.  if ($var==='')
5.  if (isset($var))
6.  if strlen($var)==0
7.  if (is_string($var))

Among the possible values that a variable might possess are the following:

1.  a string value, 'something'
2.  a numerical value, 12345
3.  the empty value, ''
4.  the integers 1 or 0
5.  the boolean constants TRUE or FALSE
6.  NULL

Or a variable might be unset.

Variables set by user input in a form

User input in response to a form can exist only as a string value. If the user inputs a number, it will be treated as a string for evaluation.

An array or a text variable coming from a form via checkbox or radio will be unset if the user doesn’t check anything. But no text variable coming from a form via input can be unset. If the user doesn’t input a value, the variable will be empty (='').

Thus, TRUE/FALSE and NULL are impossible values for form-generated variables, as are the integers (as opposed to the strings) 1 and 0.

Variables set by a script

A variable generated by a script might have any of the possible values. A variable that is conditionally generated might be unset.

This table shows how each of these possible values is evaluated by each technique (note that “unset” is not actually a value):

  typical use→variables usually with formsvariables usually with scripts
↓test | value→something12345''0FALSENULL[unset]

This table demonstrates somewhat surprising results:

  • For values like 0 (the integer), FALSE, and NULL, tests for falseness or emptiness like !$var or empty($var) or $var=='' will return true.
  • A test like strlen($var)==0 returns false when $var=0 (the integer) but true when $var=FALSE or 12345. This is particularly confusing, since none of these variables is in fact a string, and two of them are equivalent in meaning even though they are different types.

What conclusions can we draw?

  • When testing user input from a form, the only reliable test that the user has entered something is if($var===''). But if you are expecting an array back, you need to test that it has been set, with if(array()) (the isset test will not work with an array).
  • When testing a conditionally set variable, you must check whether the variable has been set with isset($var) before any further processing, because some tests return true even with an unset variable.
  • There are extremely subtle differences among these tests. These are often caused by mixing types in comparisons, like if(strlen($var)) when $var=0 (the integer). Therefore, when testing a variable set by a script, you should consider carefully exactly which test will provide the results you want. Do strict rather than loose comparisons if possible. More than one test will probably be necessary.
  • Always use the values TRUE/FALSE for boolean testing, never 1/0.
  • For a function that is expected to return a value, consider setting a return value ($var=FALSE or $var='') in case the function fails.
  • The tests if (!$var) and if (empty($var)) and if ($var=='') are completely interchangeable, and equally confusing. Each returns true for a variable that is empty or nonexistent in a general sense (either unset or ''), but also for a variable that is equal to 0 (which might be 0 the integer or FALSE the boolean, neither of which is empty or nonexistent in a general sense).

A metaphysical digression

Analyzing exactly why a test like if (!$var) returns true when $var=FALSE gets us into metaphysics: can “nothing” nevertheless be something by virtue of being the thing “nothing”? To put it another way, if 0 and FALSE and NULL are in fact some sort of values, how can the variables containing them be considered false or empty? Apparently, in some cases they are recognized as not being empty:

  • A test like isset($var) returns true for the values 0 (the integer) and FALSE, which are thus set even though supposedly they are nothing.
  • A test like strlen($var)==0 similarly returns false for the value 0 (the integer), which thus does have some length even though supposedly it is nothing.

Once again, most of these problems can be avoided by using strict comparisons, with careful attention to types so that no mixing takes place.

Information from The PHP Manual on type comparison can be found here.

Contributors to this note include the following:
Chris Snyder
Dan Convissor
Chris Shiflett
Brian Pang
Phil Powell
John Lacey
Jeff Knight
Emmanuel Decarie
the PHundamentals team: Jeff Siegel and Mike Southwell