Skip to main content

PHP empty() and the trouble of passing new zero values in forms

Lets say we have a form. The form is straight-forward: HTML radio buttons that posts to a PHP processing script that saves the results to a database. The radio buttons correspond to bindary responses to questions - Yes/No, True/False. These truth values are mapped to the integers '1' and '0', which are then stored in the database.

When such a form is creating new records, this is about as brainless as web-development gets. But things get more complicated when the form is used to update existing records. A useful update form will typically have a few basic features; among them, the option to update all of the data in the form or just some of the data. To do this, we have to check whether a variable is being updated or not.

One approach to checking on variable updates is to create an array with all of the variables to be considered, like this: 

$stuff = array( 'fee' => $_POST['fee'],
                'fi' => $_POST['fi'],
                'fo' => $_POST['fo'],
                'fum' => $_POST['fum']
               )

Then you can parse the assignments of these variables, determine their value, and decide whether to discard the variable or update your database based on it. In this example, lets imagine that the variable 'fee' also serves as a key for the database table to be updated by this script:

foreach($stuff as $variable => $value)
{
    if ( (empty($value)) && ($variable='fee') ) {
        echo "You need to provide a value for FEE to identify which record to update!";
        break;
    }
    
    elseif ( (!empty($value)) && ($variable!='fee') ) {
        $query = ("UPDATE events SET ".$variable." = '".$value."' WHERE fee = ".$_POST['fee']."");
        print $query . "<br>";
        $link->exec($query);
 echo "we updated the database with: " . $query;
        continue;
    }
    
    elseif (empty($value)) {
        print $variable . " value was not passed to database";
 continue;
    }
}

You will notice that in two of these conditional statements, empty() is used in order to identify whether a variable has been modified or not. In some circumstances this would work - for example, if this form was not multiple choice, but contained text fields, it would do a very good job at determining whether content was placed in those text fields.

The trouble comes when a value contains a Yes/True/'1' value, and we want to use the update form to change that to a No/False/'0' value. Why? Because empty() does not check whether or not a variable assignment is in fact empty. Or more specifically, that's not all it does. empty() will return a TRUE value if any of the following conditions are met:

  • "" (an empty string)
  • 0 (0 as an integer)
  • 0.0 (0 as a float)
  • "0" (0 as a string)
  • NULL
  • FALSE
  • array() (an empty array)
  • $var; (a variable declared, but without a value)
What this means is that if we use empty(), and then attempt to change a value from '1' to '0' using our form, that change will be discarded.

So what's the solution? I tend to use more specific conditionals. Instead of empty(), we can tell our script to discard variables that are actually empty in the human sense of the term (x=="") and tell our script to handle variables containing a zero value (x=='0') normally.


foreach($stuff as $variable => $value)
{
    if ( (empty($value)) && ($variable='fee') ) {
        echo "You need to provide a value for FEE to identify which record to update!";
        break;
    }
    
    elseif ( (!empty($value)) && ($variable!='fee') ) {
        $query = ("UPDATE events SET ".$variable." = '".$value."' WHERE fee = ".$_POST['fee']."");
        print $query . "<br>";
        $link->exec($query);
 echo "we updated the database with: " . $query;
        continue;
    }

    elseif ( ($value=='0') && ($variable!='fee') ) {
        $query = ("UPDATE events SET ".$variable." = '".$value."' WHERE fee = ".$_POST['fee']."");
        print $query . "<br>";
        $link->exec($query);
 echo "we updated the database with: " . $query;
        continue;
    }
 
    elseif ($value=="") {
        print $variable . " value was not passed to database";
 continue;
    }
}

Hope this helps! (DISCLAIMER: always sanitize input!)