Undefined index issues on radio buttons and checkbox - help please

Hi,

I’ve got a form which captures data into a MySQL database. Trouble is my radio buttons and checkbox both cause undefined index error messages and I don’t know how to stop them from happening. Futhermore, for some reason I need to define things twice otherwise it causes undefined index error messages as well, hence why you see $NAME = cleanInput($_POST[‘NAME’], $conn); for example near the top of the code and then further down under the // Sanitise details comment.

Really unsure how to fix these, so any help would be appreciated. For my checbox I dont need it to write anything to my database, just needs to see if its checked then allow the form to be submitted, otherwise show the error message.

The radio buttons and checkbox are the last two rows in my form table called “OVER18” and “TERMS”.


<?php
require_once('db.php');
require_once('functions.php');
// date
$DATE = date(cleanInput("Y-m-d", $conn));

$errors = array();

// If request is a form submission
if ($_SERVER['REQUEST_METHOD'] == 'POST') {

    $NAME = cleanInput($_POST['NAME'], $conn);
    $EMAIL = cleanInput($_POST['EMAIL'], $conn);
    $COMMENTS = cleanInput($_POST['COMMENTS'], $conn);
    $OVER18 = cleanInput($_POST['OVER18'], $conn);
    $TERMS = cleanInput($_POST['TERMS'], $conn);


// Validation
// Check NAME is not less than 2 characters
    if (strlen($NAME) < 2) {
        $errors['NAME'] = "Your name is not long enough";
    }

    // Check TELEPHONE is valid
    if (0 === preg_match("/^((\\(?0\\d{4}\\)?\\s?\\d{3}\\s?\\d{3})|(\\(?0\\d{3}\\)?\\s?\\d{3}\\s?\\d{4})|(\\(?0\\d{2}\\)?\\s?\\d{4}\\s?\\d{4}))(\\s?\\#(\\d{4}|\\d{3}))?$/", $_POST['TELEPHONE'])) {
        $errors['TELEPHONE'] = "Please enter valid phone number";
    }

    // Check EMAIL is not less than 2 characters
    if (strlen($EMAIL) < 2) {
        $errors['EMAIL'] = "Your email address is not long enough";
    }

    // Check COMMENTS is not less than 3 characters
    if (strlen($COMMENTS) < 3) {
        $errors['COMMENTS'] = "Please enter a comment";
    }

    // Check OVER 18
	if( !isset($_POST['radio']) || ($_POST['radio'] != 'yes' && $_POST['radio'] != 'no') ) {
   $errors['radio'] = 'Please answer this question';
	} 

    // Check TERMS have been agreed
    if ($TERMS == "No") {
        $errors['TERMS'] = "It is required of you to agree to the terms before continuing";
    }

    // If no validation errors
    if (0 === count($errors)) {

        // Sanitise details
        $NAME = cleanInput($_POST['NAME'], $conn);
        $TELEPHONE = cleanInput($_POST['TELEPHONE'], $conn);
        $EMAIL = cleanInput(trim($_POST['EMAIL']), $conn);
        $COMMENTS = cleanInput($_POST['COMMENTS'], $conn);
        $OVER18 = cleanInput($_POST['OVER18'], $conn);
        $TERMS = cleanInput($_POST['TERMS'], $conn);

        // Insert user into the database
        $query = "
    INSERT INTO
        testform  (
            DATE
          , NAME
          , TELEPHONE
          , EMAIL
          , COMMENTS
          , OVER18
          , TERMS
    ) VALUES (
            '$DATE'
          , '$NAME'
          , '$TELEPHONE'
          , '$EMAIL'
          , '$COMMENTS'
          , '$OVER18'
          , '$TERMS'
          )";


        // for debugging
        print_r($_POST);

        $result = mysqli_query($conn, $query) or die(mysqli_error($conn) . $query);

        if ($result != FALSE) {
            // Form submitted successfully
            header("Location: thankyou.php");
            exit;
        }
    }
} else {

    //  DEBUGGING ONLY - DISABLE IN PRODUCTION SITE
    // echo "<br/><br /> MySQLi Error: " . mysqli_error($conn);
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>Untitled Document</title>
        <link rel="stylesheet" type="text/css" href="styles.css" />
    </head>
    <body>
        <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="POST">       
            <table class="form">
                <tr class="<?php echo form_row_class("NAME", $errors); ?>">
                    <th><label for="NAME">Telephone</label></th>
                    <td><input name="NAME" id="NAME" type="text" value="<?php echo isset($_POST['NAME']) ? hsc($_POST['NAME']) : ''; ?>" />
                        <?php echo error_for("NAME", $errors); ?></td>
                </tr>
                <tr class="<?php echo form_row_class("TELEPHONE", $errors); ?>">
                    <th><label for="TELEPHONE">Telephone</label></th>
                    <td><input name="TELEPHONE" id="TELEPHONE" type="text" value="<?php echo isset($_POST['TELEPHONE']) ? hsc($_POST['TELEPHONE']) : ''; ?>" />
                        <?php echo error_for("TELEPHONE", $errors); ?></td>
                </tr>
                <tr class="<?php echo form_row_class("EMAIL", $errors); ?>">
                    <th><label for="EMAIL">Email Address</label></th>
                    <td><input name="EMAIL" id="EMAIL" type="text" value="<?php echo isset($_POST['EMAIL']) ? hsc($_POST['EMAIL']) : ''; ?>" />
                        <?php echo error_for("EMAIL", $errors); ?></td>
                </tr>
                <tr class="<?php echo form_row_class("COMMENTS", $errors); ?>">
                    <th><label for="COMMENTS">Comments</label></th>
                    <td><textarea name="COMMENTS" id="COMMENTS"><?php echo isset($_POST['COMMENTS']) ? hsc($_POST['COMMENTS']) : ''; ?></textarea>
                        <?php echo error_for("COMMENTS", $errors); ?></td>
                </tr>

                <tr class="<?php echo form_row_class("OVER18", $errors); ?>">
                    <th><label for="OVER18">Tick box to agree to terms and conditions</label></th>
                    <td colspan="2">
					
					<label for="OVER18_YES">Yes</label>
					<input type="radio" name="OVER18" id="OVER18_YES value="yes" <?php echo isset($_POST['OVER18']) && $_POST['OVER18'] == 'yes' ? 'checked="checked"' : ''; ?>/>
					<label for="OVER18_NO">NO</label>
					<input type="radio" name="OVER18" id="OVER18_NO" value="no" <?php echo isset($_POST['OVER18']) && $_POST['OVER18'] == 'no' ? 'checked="checked"' : ''; ?>/>
		
                        <?php echo error_for("OVER18", $errors); ?></td>
                </tr>

                <tr class="<?php echo form_row_class("TERMS", $errors); ?>">
                    <th><label for="TERMS">Tick box to agree to terms and conditions</label></th>
                    <td colspan="2">
                        <input type="checkbox" name="TERMS" id="TERMS" value="Agreed" <?php echo isset($_POST['TERMS']) && $_POST['TERMS'] == 'Agreed' ? 'checked="checked"' : ''; ?>/> />
                        <?php echo error_for("TERMS", $errors); ?></td>
                </tr>
                <tr>
                    <th></th>
                    <td>
                        <input type="submit" value="Go!" /></td>
                </tr>
            </table>
        </form>
    </body>
</html>

The basic problem is that unchecked checkboxes do not post anything. It’s an HTML issue. Nohting PHP can do about it.

So if TERMS is unchecked then $_POST[‘TERMS’] will trigger an undefined index error message. You can use isset($_POST[‘TERMS’] to test if terms was posted.

Another trick is to add <input type=“hidden” name=“TERMS” value=“0” /> before the check box item. This will ensure that you always get a TERMS posted.

Hi ahundiak,

Not sure what you mean sorry. I’ve already got an isset($_POST[‘TERMS’] in my code (see block of code taken out below), unless you mean add it to the second $_POST?

As for hiding the field, how will they check the checkbox to agree to the terms if it’s hidden. Sorry if I’ve missed the obvious here!

 <input type="checkbox" name="TERMS" id="TERMS" value="Agreed" <?php echo isset($_POST['TERMS']) && $_POST['TERMS'] == 'Agreed' ? 'checked="checked"' : ''; ?>/> />
 <?php echo error_for("TERMS", $errors); ?></td>

$TERMS = cleanInput($_POST[‘TERMS’], $conn);

Again, even though your html contains <input type=“checkbox” name=“TERMS” />, you will not actually receive a $_POST[‘TERMS’] value unless the check box is checked. It’s seems a bit strange the first time you encounter it.

One way to get around this is to:

<input type=“hidden” name=“TERMS” value=“0” />
<input type=“checkbox” name=“TERMS” id=“TERMS” value=“Agreed” />

If the user doesn’t check the terms box then a value of 0 will be posted for TERMS. Bit of a hack but it works well.

Ahhhh ok I see now, thanks for explaining :slight_smile:

So with regard to for example my NAME field, howecome I have to define $NAME = cleanInput($_POST[‘NAME’], $conn); at the top and then further down my page under the if (0 === count($errors)) { ? Is this another case of it needing isset? I’m new to this, so sorry if this is obvious. Would it be a case of doing the following?


	if (!isset($_POST['$NAME']) || (strlen($NAME) < 2)) {
		$errors['NAME'] = "Your name is not long enough";
} 

Futhermore, would I need to do a hidden input for both the radio buttons just like with the checkbox?

I don’t really know why you are pulling data out from POST twice. No need for it. Generally best to just gather up your data in one spot and then not worry about it.

You have a function called cleanInput which is great. I would have it do the isset for you by passing the name of the parameter you want:


function cleanInput($data,$name,$conn)
{
    if (!isset($data[$name])) return null;
    $value = $data[$name];

    // Clean value then return it
    return $value;
}

That should eliminate the need for any more isset($_POST) as well as hidden inputs.

The first part of your code should then look like:


$errors = array();

// If request is a form submission
if ($_SERVER['REQUEST_METHOD'] != 'POST') 
{
    // Init your data
    $name = $email = $comments = $over18 = $terms = null;
}
else
{
    // Gather up posted data, use lower case for variable names, no need to shout
    $name = cleanInput($_POST,'NAME', $conn);
    $email = cleanInput($_POST,'EMAIL', $conn);
    $comments = cleanInput($_POST,'COMMENTS', $conn);
    $over18 = cleanInput($_POST,'OVER18', $conn);
    $terms = cleanInput($_POST,'TERMS', $conn);

    // No need to use $_POST anymore in this script
    // Do your validation and update the database
}
// Generate your html using $name,$email etc.

Thanks :slight_smile:

My cleanInput function currently does the following which I like for santising the data, therefore how would I use the version of the function you posted and include what I’ve added? Or would they be two sepperate functions? How would that code look if they were just the one function?

My cleanInput function


function cleanInput($data, $conn) {
    if (get_magic_quotes_gpc()) {
        $data = stripslashes($data);
        $data = strip_tags($data);
        $data = mysqli_real_escape_string($conn, $data);
    } else {
        $data = strip_tags($data);
        $data = mysqli_real_escape_string($conn, $data);
    }
    return $data;
}

With regard to the second block of code in your last post, where would all my regular validation stuff go? Would it go in the else statment where you put the comment " // Gather up posted data, use lower case for variable names, no need to shout"?

Thanks for all your help, really appreciated :smiley: