Welcome Guest, Not a member yet? Register   Sign In
[Newbie Guide: Good Practices] Proper Comparisons For undefined values in PHP
#1

[eluser]Aea[/eluser]
I'm going to give a try at writing a new newbie guides to address problems I see in beginning programmers code, if you like where I'm going, found this helpful, have suggestions, or just want to flame me, just leave a response Smile

PHP is known, and generally despised by many programmers for having extremely loose comparison checking, and this is abused resulting in not only unreadable code, but unexpected problems later down the line which can be a headache to find.

A common comparison I see is...

Code:
$var == ""

Now what this does is cast $var to a string and then evaluate the expression, for instance...

Code:
var_dump(NULL == ''); // bool(true)

But what if your string legitimately is blank, suddenly your code thinks that it your variable doesn't exist when it does, so how do we solve this?

1) Always Check For An Explicit Value when you want to see if something is undefined
2) Always Use === When Doing This

So what values are good for checking for undefined data? NULL or FALSE (Although I strongly advocate the use of NULL the choice is left up to you). This way you can be certain that the value truly is intended to be undefined.

Code:
if($var === NULL)
{
    echo 'This is a good comparison for an undefined variable OR value of the variable.';
}

But what about 0 and 1? This is a terrible way to compare TRUE and FALSE. Firstly, it's not obvious when viewing your code, and secondly it can be prone to the same problems as above unless you use the === operator. You need to use the === operator because otherwise...

Code:
var_dump('' == 0); // bool(true)

And same for...

Code:
var_dump('0' == 0); // bool(true)

This is both unintuitive, and could lead to problems when your value is intentionally (string) '0'.

Note: Languages w/ concrete data types may use bit values 1 and 0 for TRUE and FALSE respectively, but PHP doesn't have concrete data types so it's a bad idea, stick with TRUE and FALSE within your code to be completely explicit.

I also previously mentioned preferring NULL over FALSE for this, my primary motivation is that I see FALSE being used as a boolean flag, i.e. it's something I explicitly may set, whereas NULL is indicative of an undefined variable or value (you can set a variable value to NULL).

If you're pulling in data from an non-script source you may benefit greatly from checking whether the variable is set, this is not an issue when you have a high error reporting threshold, but I prefer to develop with a low threshold so I can catch all errors. PHP believes that an undefined index is a problem, and I agree, here's how you get around it...

Code:
// Grabs a variable from $_GET
$var = isset($_GET['CODE']) ? $_GET['CODE'] : NULL;

Flaws? For one values such as '' (empty string) are accepted, you may want to filter this out if you want an empty string to come across as an NULL value, or let your validation code handle it. Don't use isset($var{0}) unless you're explicitly expecting string data, since the results will be unpredictable (on the other hand it is a quick, if unintuitive way to check for string data).

Doing isset() every time can be uncomfortable, here's a quick wrapper for it:

Code:
function getValue($mixValue)
{
    return isset($mixValue) ? $mixValue : NULL;
}

This code has an additional benefit, if you pass in something like FALSE it will return true, because FALSE is explicitly set (this is very useful for importing flags).


Quick Wrapup
- If you're testing for undefined data, test for it being NULL, not for '' (empty string) or 0 (bit flag for FALSE, because this isn't C).
- If you want to pull in variables that you may not know exist simply use an isset()


More Tests
Code:
<?php

$arrInput = array(0, '0', '', 1, '1', NULL, FALSE);

echo 'Comparison With isset()'.PHP_EOL;

foreach($arrInput as $mixValue)
{
    echo 'Testing:'.PHP_EOL;
    var_dump($mixValue);
    var_dump(isset($mixValue));
    echo PHP_EOL;
}

echo 'Comparison With != 0'.PHP_EOL;

foreach($arrInput as $mixValue)
{
    var_dump($mixValue);
    var_dump($mixValue != 0);
    echo PHP_EOL;
}

echo 'Comparison With != \'\''.PHP_EOL;


foreach($arrInput as $mixValue)
{
    echo 'Testing:'.PHP_EOL;
    var_dump($mixValue);
    var_dump($mixValue != '');
    echo PHP_EOL;
}
#2

[eluser]Mackstar[/eluser]
Thanks for the write up.. I am feeling guilty!

Yes I do believe we need more efficient coding techniques rather than hang on to php's flexibility that results in sloppy code.

Cheers

Richard
#3

[eluser]xwero[/eluser]
Instead of checking for undefined variables, set as many variables as possible with the correct type
Code:
$string = '';
$array = array();
$numeric = 0;
$boolean = false;
If a variable is undefined is certain situations this will be intentional.

Aea the problem with your getValue function is that php will complain about the none existing variable, a quick fix is to pass the variable name as a string
Code:
function getValue($mixValue)
{
    return isset(${$mixValue}) ? ${$mixValue} : NULL;
}
#4

[eluser]Aea[/eluser]
One would hope you're passing "something" to the getValue function without resolving to variable variables, but that's a valid solution to the problem in my eyes.




Theme © iAndrew 2016 - Forum software by © MyBB