Categories
PHP

Form Validation

Form validation is one of the most important parts of a website, in this tutorial you’ll learn how to validate a form and how to display error messages with the form.

To make our code flexible and understandable we divided the code into multiple functions:

  1. printForm() function displays the HTML form to the user.
  2. checkForm() function validates each form element using the following helper functions:
    1. isValidUsername()
    2. isValidPassword()
    3. isValidEmail()
    4. isValidUrl()
  3. saveFormData() function can save form data on your server.

First, we use the $_SERVER['REQUEST_METHOD'] to determine the form status. If the form is not posted we show the form with printForm() to the user. If the form is posted, we validate the form with checkForm(), if validation failed we show the form and errors with printForm($errors).

<?php
 // form.php
 if ($_SERVER['REQUEST_METHOD'] == 'POST') {
  $errors = checkForm($_POST);
  if ( empty ( $errors ) )
   saveFormData($_POST);
  else
   printForm($errors);
 }
 else
  printForm();

 function printForm ( $errors = [] ) {
  // Display the HTML form
 }

 function checkForm ( $form ) {
  // Validate form elements
 }

 function saveFormData ( $form ) {
  // Logic to save form data
 }

The saveFormData() function is called on successful validation of the form. You can use this function to save the data in the database, file, etc.

Print form – printForm()

This form contains four text fields (see Prefilling text fields), you must enter the valid data for successful submission of the form. If the validation failed, the form shows the errors on each field where the validation failed.

<?php
 function printForm($errors = []) {
?>
<style>form span{color:red}</style>

<form method="post" action="form.php">
 Username: <span>* <?= $errors['username'] ?? '' ?></span><br>
 <input type="text" name="username"
   value="<?= htmlspecialchars( $_POST['username']  ?? '') ?>">

 <br><br>
 Password: <span>* <?= $errors['password'] ?? '' ?></span><br>
 <input type="password" name="password"
   value="<?= htmlspecialchars( $_POST['password']  ?? '') ?>">

 <br><br>
 Email:   <span>* <?= $errors['email'] ?? '' ?></span><br>
 <input type="text" name="email"
   value="<?= htmlspecialchars( $_POST['email']  ?? '') ?>">
  
 <br><br> 
 URL:   <span><?= $errors['url'] ?? '' ?></span><br>
 <input type="text" name="url"
   value="<?= htmlspecialchars( $_POST['url']  ?? '') ?>">

 <br><br>
 <input type="submit" name="submit" value="submit">
</form>
<?php	 
 }

Note:

  1. <?='Hello'?> is the short form of <?php echo 'Hello'; ?>
    See PHP shortcut to print or echo
  2. The ?? (null coalescing operator) is available since PHP 7.0, alternatively, you can use isset() function, see the following example:
<?php
 // Only works with PHP 7.0 or above
 $url = $_POST['url'] ?? '';

 // For all version of PHP
 $url = isset($_POST['url']) ? $_POST['url'] : '';
 
// OR
 if (isset ($_POST['url']) ) {
  $url = $_POST['url'];
 } else {
  $url = '';
 }

Validate form – checkForm()

The checkForm($_POST) initiated form validation. The $_POST (super global array) is an associative array of variables that contains the form data.

The checkForm() function validates the form elements and if the validation failed it returns an associative array of error messages otherwise returns an empty array. Array keys represent the name of the form fields and values are the error message to display on the form.

<?php
 // ... ... ...
 $errors = checkForm($_POST);

 function checkForm($form){
  $m = []; // $m = array();
  
  #$username = isset($form['username']) ? trim($form['username']) : '';
  $username = trim ( $form['username'] ?? '' );
  $password = trim ( $form['password'] ?? '' );
  $email    = trim ( $form['email'] ?? '' );
  $url      = trim ( $form['url'] ?? '' );
  
  if ( ! isValidUsername($username))
   $m['username'] = 'Use alphanumeric, underscore and hyphen characters. Length must be between 4 and 10 characters';

  if ( ! isValidPassword($password) )
   $m['password'] = 'Must be between 6 and 32 characters. Must have at least one uppercase, one lowercase, one numeric and one symbol character.';

  if ( ! isValidEmail($email) )
   $m['email'] = 'Invalid email format.';  

  // URL is optional
  if ( $url != '' && (! isValidUrl($url)) )
   $m['url'] = 'URL must start with http:// or https:// protocol';

  return $m;
 }

All fields are mandatory except the URL field which is optional. An optional field will not check if it is empty. The expression $url != "" tells PHP to validate the URL if it is not empty.

Username validation

Requirements:

  • Minimum length: 4-character.
  • Maximum length: 10-character.
  • Allowed characters: alphanumeric (A-Z, a-z, 0-9), hyphen and underscore.
  • Underscore and hyphen:
    • can not be used together i.e. -_ or _-.
    • can not be used twice at once i.e. -- or __.
    • can not be used at the beginning or end of the string (username), i.e. -user, _user, user-, or user_.

We created a function isValidUsername() that accepts the username as a string and checks its length and tests it with regular expression. The function returns false if the username does not meet our requirements otherwise return true.

<?php
 function isValidUsername($username) {
  $len = strlen($username);
  if ( $len < 4  || 
       $len > 10 ||
       preg_match('/[^a-z0-9_-]|--|__|-_|_-|^[-_]|[-_]$/i',$username)
     )
   return false;
  return true;
 }

Explaining regex pattern:

We used preg_match function to match username with our patterns, we used seven patterns separated by | pipe sign: (See, Regular Expressions)

  1. [^a-z0-9_-] matches any character other than the alphanumeric, underscore and hyphen characters
  2. -- matches double hyphen.
  3. __ matches double underscore.
  4. -_ matches hyphen followed by an underscore.
  5. _- matches underscore followed by a hyphen.
  6. ^[-_] matches if the string starts with a hyphen or underscore.
  7. [-_]$ matches if the string ends with a hyphen or underscore.

Password validation

Requirements:

  • Minimum length: 6-character.
  • Maximum length: 32-character.
  • Password must have at least:
    • one uppercase character
    • once lowercase character
    • one numeric character
    • one symbol character, i.e. !, #, @, etc.

To validate the password, we created isValidPassword() function that accepts the password as a string and checks its length and tests it with regular expression. The function returns false if the password does not meet our requirements otherwise return true.

<?php
 function isValidPassword($password) {
  $len = strlen($password);
  $qt  = preg_quote('`~!@#$%^&*()_-=+\|[]{}/?.<>,\'";:','/');
  if ( $len < 6  || $len > 32 ||
   !preg_match('/(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*['.$qt.'])/',
     $password))
   return false;
  return true;
 }

Explaining password validation function:

  • The strlen function counts the number of characters in the string.
  • The preg_quote function quotes regex special characters: . \ + * ? [ ^ ] $ ( ) { } = ! < > | : – #.
  • The preg_match function matches the password with the given pattern using lookahead expressions:
    • (?=.*[A-Z]) matches an uppercase character
    • (?=.*[a-z]) matches a lowercase character
    • (?=.*[0-9]) matches a numeric character
    • (?=.*['.$qt.']) matches a special character (quoted with preg_quote)

Email validation

The PHP’s filter_var function has a FILTER_VALIDATE_EMAIL property that returns false if the email entered is not in the proper format. In the following code, we created a function isValidEmail() that used this property to validate the given email:

<?php
 function isValidEmail($email) {
  if (filter_var($email, FILTER_VALIDATE_EMAIL) === FALSE)
   return false;
  return true;
 }

For details visit: Validating email with filter_var() and checkdnsrr().

Url validation

The PHP’s filter_var function has a FILTER_VALIDATE_URL property that returns false if the URL entered is not in the proper format. In the following code, we created a function isValidUrl() that used this property to validate the given URL:

<?php
 function isValidUrl($url) {
  if (filter_var($url, FILTER_VALIDATE_URL) === FALSE
      || !str_starts_with($url, 'http')
  )
   return false;
  return true;
 }

Saving form data – saveFormData()

After completing the validation it’s time to further process the data for saving it into the database or a file or send it to an email address, all these tasks will be discussed later in subsequent tutorials. For now, we just display a message to the user to indicate that form validation has been passed.

<?php
 function saveFormData() {
  echo '<h1>Form Submitted</h1>';	 
 }

Complete Form Validation Script:

<?php
 if ($_SERVER['REQUEST_METHOD'] == 'POST') {
  $errors = checkForm($_POST);
  if ( empty ( $errors ) )
   saveFormData($_POST);
  else
   printForm($errors);
 } else {
   printForm();
 }

 function printForm($errors = []) {
?>
<style>form span{color:red}</style>
<form method="post" action="form.php">

 Username: <span>* <?= $errors['username'] ?? '' ?></span><br>
 <input type="text" name="username" value="<?= htmlspecialchars( $_POST['username']  ?? '') ?>">

 <br><br>
 Password: <span>* <?= $errors['password'] ?? '' ?></span><br>
 <input type="password" name="password" value="<?= htmlspecialchars( $_POST['password']  ?? '') ?>">

 <br><br>
 Email:   <span>* <?= $errors['email'] ?? '' ?></span><br>
 <input type="text" name="email" value="<?= htmlspecialchars( $_POST['email']  ?? '') ?>">
  
 <br><br> 
 URL:   <span><?= $errors['url'] ?? '' ?></span><br>
 <input type="text" name="url" value="<?= htmlspecialchars( $_POST['url']  ?? '') ?>">

 <br><br>
 <input type="submit" name="submit" value="submit">
</form>
<?php	 
 }
 
 function checkForm($form){
  $m = [];
  
  $username = trim ( $form['username'] ?? '' );
  $password = trim ( $form['password'] ?? '' );
  $email    = trim ( $form['email'] ?? '' );
  $url      = trim ( $form['url'] ?? '' );
  
  if ( ! isValidUsername($username))
   $m['username'] = 'Use alphanumeric, underscore and hyphen characters. Length must be between 4 and 10 characters';

  if ( ! isValidPassword($password) )
   $m['password'] = 'Must be between 6 and 32 characters. Must have at least one uppercase, one lowercase, one numeric and one symbol character.';

  if ( ! isValidEmail($email) )
   $m['email'] = 'Invalid email format.';  

  // URL is optional
  if ( $url != '' && (! isValidUrl($url)) )
   $m['url'] = 'URL must start with http:// or https:// protocol';

  return $m;
 // $m['select'] = 'Invalid data';
 }

 function isValidUsername($username) {
  $len = strlen($username);
  if ( $len < 4  || 
       $len > 10 ||
       preg_match('/[^a-z0-9_-]|--|__|-_|_-|^[-_]|[-_]$/i',$username)
     )
   return false;
  return true;
 }
 
 function isValidPassword($password) {
  $len = strlen($password);
  $qt  = preg_quote('`~!@#$%^&*()_-=+\|[]{}/?.<>,\'";:','/');
  if ( $len < 6  || $len > 32 ||
   !preg_match('/(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*['.$qt.'])/',
     $password))
   return false;
  return true;
 }
 
 function isValidEmail($email) {
  if (filter_var($email, FILTER_VALIDATE_EMAIL) === FALSE)
   return false;
  return true;
 }
 
 function isValidUrl($url) {
  if (filter_var($url, FILTER_VALIDATE_URL) === FALSE
      || !str_starts_with($url, 'http')
  )
   return false;
  return true;
 }
 
 function saveFormData() {
  echo '<h1>Form Submitted</h1>';	 
 }

Demo: Form Validation


Processing Forms in PHP: