We’ve all done it. It starts as a single IF statement:
if (empty($var)){ // does it exist? $error = 'No username entered'; return $error; } // everything is OK |
Then we decide, we need to check something else, so we just add in one more IF statement:
if (empty($var)){ // does it exist? $error = 'No username entered'; return $error; if (strlen($var) > 20){ // Is it too long? return 'Invalid username'; } } // everything is OK |
Suddenly, after some more additions and validation, you’re suddenly stuck with 4 nested IF statements and it’s starting to get messy.
if (empty($var)){ // does it exist? $error = 'No username entered'; return $error; if (strlen($var) > 20){ // Is it too long? return 'Invalid username length (20 character max)'; // Uses an imaginary function called valid_characters() if (!valid_characters($var)){ return 'Invalid characters used (letters, numbers, underscore only)'; // Check database for existing username using imaginary function db_username_exists() if (db_username_exists($var)){ return 'Username already exists (try again)'; } } } } // everything is OK |
Let’s explore two methods of improving this (Hint: The last one is my recommendation).
Bitwise Assignment Operators &= and |=
An exceptionally clear example on php.net explains:
$a &= $b is equivalent to $a = $a & $b Bitwise And $a |= $b is equivalent to $a = $a | $b Bitwise Or |
Let’s look at this in terms of our previous example:
$valid = true; // Set the expectation $valid = !empty($var); // does it exist? $valid &= !(strlen($var) > 20); // Is it too long? if ($valid){ // everything is OK } |
This example can also be displayed as:
$valid = true; // Set the expectation // Valid only if it exists and it's not too long $valid = !empty($var) && !(strlen($var) > 20); if ($valid){ // everything is OK } |
However, now we have a problem. We’ve lost the individualized error messages. Sure, you can have code comments, but let’s look at another solution.
Using a Do-While Loop
A do-while loop executes prior to the evaluation. More importantly, you can break out of it, so no need to nest; stack instead!
$error = false; do { // Did they enter anything? if (empty($var)){ $error = 'No username entered'; break; } // Is it too long? if (strlen($var) > 20){ $error = 'Invalid username length (20 character max)'; break; } // Uses an imaginary function called valid_characters() if (!valid_characters($var)){ $error = 'Invalid characters used (letters, numbers, underscore only)'; break; } // Check database for existing username using imaginary function db_username_exists() if (db_username_exists($var)){ $error = 'Username already exists (try again)'; break; } // everything is OK } while(false); if ($error){ return $error; } |
One of the great uses, as demonstrated above, is providing error responses that increase in specificity. More importantly, the least complex evaluations require less work by PHP to process, so running them first then breaking out is a great way to make sure your code isn’t working too hard. Most importantly, your code, comments, and overall flow is much cleaner and easier to review later.
Just what I was looking for, I like that solution, it’s much more readable, extensible and maintainable than nested if statements.
Thanks a bunch.