Form processing

Form basics

This is a basic HTML form.

<form action="register.php" method="post">
  <input type="text" name="first_name" value="" />
  <input type="text" name="last_name" value="" /><br />
  <input type="text" name="email" value="" /><br />
  <input type="text" name="username" value="" /><br />
  <input type="password" name="password" value="" /><br />
  <br />
  <input type="submit" name="submit" value="Submit" />
</form>

This form will submit the values of its input fields to "register.php" using the request method "POST".

The values will be packaged up and sent as "POST data". We don't see POST data in the URL like we do with GET data, and POST data does not need to be encoded or decoded like GET data does.

Even though POST data is not as prominently visible, do not be fooled into thinking they are private. Anyone who can see the request will see the POST data in plaintext.


Retrieving form values

PHP is helpful for processing form values. PHP automatically assigns the form data to the associative array in superglobal $_POST. Those values can be accessed using their key names.

<?php
  $first_name = $_POST['first_name'];
  $last_name = $_POST['last_name'];
?>

It is a good practice to make sure that values are set for variables before using them, and to set default values if they are not set.

<?php
  $first_name = isset($_POST['first_name']) ? $_POST['first_name'] : '';
  $last_name = isset($_POST['last_name']) ? $_POST['last_name'] : '';
?>

The boolean ? true\_result : false\_result syntax is called a ternary operator and is handy for writing an if-else statement on one line. PHP 7 added a new null coalesce operator (??) to make it even shorter and easier.

<?php // PHP 7.0+ only
  $first_name = $_POST['first_name'] ?? '';
  $last_name = $_POST['last_name'] ?? '';
?>

Detecting form submission

A common form-processing technique is to have a page which responds differently depending on whether a form has been submitted to it. There are two techniques to detect when a form has been submitted.

The first technique is to check the value of REQUEST_METHOD.

<?php
if($_SERVER['REQUEST_METHOD'] == 'POST') {
  // is a POST request
} else {
  // is not a POST request
}
?>

This can be packaged up as an easy-to-remember function.

<?php
function is_post_request() {
  return $_SERVER['REQUEST_METHOD'] == 'POST';
}

if(is_post_request()) {
  // is a POST request
}
?>

The second technique is to put a name/value pair on the submit input and then detect if there is a value set for $_POST['submit'].

<input type="submit" name="submit" value="Submit" />
<?php
  if(isset($_POST['submit']) {
    // form was submitted
  } else {
    // form was not submitted
  }
?>

Note that name="submit" is optional for the form to work, but required for this technique to work. HTML inputs without names are not included in the form data.


Form submitting to itself

Another common form-processing technique is for a form to submit back to its own page. The first request for the page (GET, when the URL is entered) shows the form. The second request for the page (POST, when the form is submitted) will process the form. This has the advantage of making it easy to redisplay the form again if there are errors and to re-populate its input fields with the recently submitted values.


Handling form errors

If something goes wrong during form processing, then the error needs to be communicated to the user so they can fix the data and try again.

Here is a code example which will take an array of errors and output them as a list inside a div for display on the form page.

<?php
  function display_errors($errors=[]) {
    $output = '';
    if (!empty($errors)) {
      $output .= "<div class=\"errors\">";
      $output .= "Please fix the following errors:";
      $output .= "<ul>";
      foreach ($errors as $error) {
        $output .= "<li>{$error}</li>";
      }
      $output .= "</ul>";
      $output .= "</div>";
    }
    return $output;
  }
?>

Listing all errors above the form is the easiest approach. More complex code could be written which would highlight each input field that has an error.


Redisplaying the form

If there are form errors, then the form should be redisplayed to the user and be pre-populated with the recently submitted data. It would be very frustrating to the user if they had to fill out the entire form again.

To add the values, the HTML form seen earlier will be modified to include values output by PHP.

<form action="register.php" method="post">
  <input type="text" name="first_name" value="<?php echo $first_name; ?>" />
  <input type="text" name="last_name" value="<?php echo $last_name; ?>" /><br />
  <input type="text" name="email" value="<?php echo $email; ?>" /><br />
  <input type="text" name="username" value="<?php echo $username; ?>" /><br />
  <input type="password" name="password" value="<?php echo $password; ?>" /><br />
  <br />
  <input type="submit" name="submit" value="Submit" />
</form>

Make sure that all variables being used either have a $_POST value or have a default value set.

Fork me on GitHub