PHP Form Validation
Introduction
You need to validate the information that your Web page users enter into your HTML forms. You
are inviting disaster if you don't, especially if you use the form's information to add information
to your database. You don't want junk in your database!
Form validation can be done in both the browser (called "Client-Side Validation"), usually
with JavaScript; and at the Web server (called "Server-Side Validation"), which you can
use PHP for quite easily.
And in fact, in the real world a combination of JavaScript and PHP for form validation is a good idea.
JavaScript
is quick, does not require another page load from the server, and is fairly simple. But what if the user has
turned off JavaScript, or their browser doesn't run your JavaScript code quite like you intended? PHP form
validation can't be bypassed, so it will always protect your data.
This handout will not cover JavaScript form validation. If you want to learn how
to use JavaScript for
form validation, there are many good online tutorials, and you can also take my JavaScript class
here at Richland in the fall semester!
Simple Form Validation
Before we talk about the Validator Class in most of the rest of this handout, I also want to give you an
idea of how simply form validation can be done with PHP, if you have a very simple form and you don't need
a lot of fancy validation.
For this simple validation example, we will be using this form.
Here is the form input page, simpleForm.html:
<!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" xml:lang="en" lang="en">
<head>
<title>Simple Form Validation</title>
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<style type="text/css">
body { font-family: Arial, sans-serif; }
</style>
</head>
<body>
<h3>Fill in this form and click the "Send Your Information" button:</h3>
<form method="post" action="simpleFormValidation.php">
Your name:
<input type="text" name="YourName" />
<br /><br />
Your age:
<input type="text" name="YourAge" />
<br /><br />
<input type="submit" value="Send Your Information" />
</form>
</body>
</html>
And now here is the form's action page, simpleFormValidation.php:
<!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" xml:lang="en" lang="en">
<head>
<title>Simple Form Validation</title>
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<style type="text/css">
body { font-family: Arial, sans-serif; }
</style>
</head>
<body>
<h3>Your Form Validation Results:</h3>
<p>
<?php
$yourName = $_POST["YourName"];
$yourAge = $_POST["YourAge"];
if ($yourName == "" || $yourAge == "")
{
print "Please go back and fill in your:<br />";
if ($yourName == "")
{
print "<br />Name";
}
if ($yourAge == "")
{
print "<br />Age";
}
}
else
{
print "Your Age: " . $yourAge . "<br />";
print "Your Name: " . $yourName;
print "<h4>Thank you!</h4>";
}
?>
</p>
</body>
</html>
Please note these points about the above code pages:
-
In the first page, which is the HTML form page, the form tag's action
attribute has a value that is the second, PHP page.
-
The action page assigns the form-field values to two "working"
variables. This step is not necessary, but it
can save some typing later in the code.
-
Now the action page tests to see if either of the form's values
is empty. If so, some information is displayed to the user,
instructing them to go back to the form page and fill in the
missing information.
-
If there is no missing information, the action page displays
the user's information.
A Validator Class
Here is the test form
that we will be discussing in the rest of this handout.
The PHP form validation that is described in this handout uses a PHP class (object) to do the work of
validation. This use of a class/object is an advantage because the class can be extended if needed
in your form, without changing the class definition itself. In other words, you can build your own
class by inheriting most of the code from the original class file, and adding or changing only what you need
for your specific form. The class definition given in this handout covers the most common types of
form validation that are needed.
The class is called FormValidator.
The FormValidator class has many methods that do the work of validating the data.
Some (not all) of these methods are:
- isEmpty($var, $errormsg) - check whether the specified form variable is empty;
- isString($var, $errormsg) - check whether the specified form variable contains string data;
- isNumber($var, $errormsg) - check whether the specified form variable contains numeric data;
- isWithinRange($var, $errormsg, $min, $max) - check whether the specified form variable contains a value within
the specified numeric range;
- isEmailAddress($var, $errormsg) - check whether the specified form variable contains a valid email address;
- isError() - check whether any errors have occurred in form validation;
- getErrorList() - return the list of validation errors;
- resetErrorList() - reset the error list.
- getFormattedErrorList() - return a FORMATTED list of errors;
The FormValidator class uses an associative array to store any error messages
that will be presented to the user if any of their data are incorrect.
Here is the very beginning of the FormValidator class code:
class FormValidator
{
... stuff goes here ...
}
Properties
Now let's look at the properties that are defined in the FormValidator class:
class FormValidator
{
//
// private variables
//
var $_errorList;
... more stuff goes here ...
}
Please note the underscore (_) that is in the variable (property) name. In
this code, an underscore in a variable name is used to indicate that the variable is a private (local)
variable.
_getValue() Method
As we look at the validation methods in just a few minutes, you will see that
each validation method will be passed the name of the form variable to be tested,
as a string. We need a method which will take this string, and use it
to obtain the value of the corresponding form variable.
Here is that method:
class FormValidator
{
// snip
//
// methods (private)
//
// function to get the value of a variable (field)
function _getValue($field)
{
if (isset($_POST["{$field}"]))
{
return $_POST["{$field}"];
}
else
{
return "";
}
}
// snip
}
The _getValue() method will be passed a string representing a particular form variable -
for example, "a" - and it will return the value of the corresponding form variable - for
example, $_POST["a"]. Note how this code uses PHP's powerful variable interpolation features to
return the form value.
isEmpty()
The isEmpty() public method is called with two arguments:
- the name of the form variable to be tested, and
- the error message to be displayed if it is found to be empty.
This method internally calls the _getValue()
method (see the previous section) to obtain the value of the named form variable;
it then trim()s
this value and checks to see if it is empty.
class FormValidator
{
// snip
//
// methods (public)
//
// check whether input is empty
function isEmpty($field, $msg)
{
$value = $this->_getValue($field);
if (!is_array($value) && trim($value) == "")
{
$this->_errorList[] = array("field" => $field,
"value" => $value, "msg" => $msg);
return true;
}
else
{
return false;
}
}
// snip
}
Please note these further points about the above code:
-
If the variable is empty, a new element is added to the private class variable
$_errorList (an array) to represent the error. This new element
is itself a three-element associative array, with the keys
"field", "value" and "msg", representing the form variable name, the current
value of that variable, and the corresponding error message respectively. The method
then returns true.
-
If the variable is not empty, it will pass the test and
the method will simply return false.
-
The $this prefix provides a convenient way to access variables
and functions which are "local" to the class.
isString()
This method simply uses PHP's built-in variable functions to determine whether
the data passed to it is character data.
class FormValidator
{
// snip
// check whether input is a string
function isString($field, $msg)
{
$value = $this->_getValue($field);
if(!is_string($value))
{
$this->_errorList[] = array("field" => $field,
"value" => $value, "msg" => $msg);
return false;
}
else
{
return true;
}
}
}
isNumber()
This method simply uses PHP's built-in variable functions to determine whether
the data passed to it is numeric data.
Also see the next two sections for isInteger() and isFloat().
class FormValidator
{
// snip
// check whether input is a number
function isNumber($field, $msg)
{
$value = $this->_getValue($field);
if(!is_numeric($value))
{
$this->_errorList[] = array("field" => $field,
"value" => $value, "msg" => $msg);
return false;
}
else
{
return true;
}
}
}
isInteger()
This useful corollary of the isNumber() method provides
for more precise data validation capabilities when dealing with numeric data. Also
see the next section for isFloat().
class FormValidator
{
// snip
// check whether input is an integer
function isInteger($field, $msg)
{
$value = $this->_getValue($field);
if(is_numeric($value))
{
if(floatval($value) != intval(floatval($value)))
{
$this->_errorList[] = array("field" => $field,
"value" => $value, "msg" => $msg);
return false;
}
else
{
return true;
}
}
else
{
$this->_errorList[] = array("field" => $field,
"value" => $value, "msg" => $msg);
return false;
}
}
}
Please note these points about the above code:
-
floatval() is a built-in PHP function which converts
a value to a float-type number.
-
intval() is a built-in PHP function which converts
a value to an integer-type number.
-
If you convert a value to an integer type, then you convert
the same value to a floating-point type, and you then compare the
converted values,
you can tell if the (original) value is an integer or not.
- If the integer type and the floating-point type are
equal,
you have an integer to start with.
- If the integer type and the floating-point type
are unequal,
you have a floating-point number to start with, not an integer.
isFloat()
This useful corollary of the isNumber() method provides
for more precise data validation capabilities when dealing with numeric data. Also
see the previous section for isInteger().
class FormValidator
{
// snip
// check whether input is a float
function isFloat($field, $msg)
{
$value = $this->_getValue($field);
if(is_numeric($value))
{
$castValue = (float)$value;
if(!is_float($castValue))
{
$this->_errorList[] = array("field" => $field,
"value" => $value, "msg" => $msg);
return false;
}
else
{
return true;
}
}
else
{
$this->_errorList[] = array("field" => $field,
"value" => $value, "msg" => $msg);
return false;
}
}
}
Please note these points about the above code:
isWithinRange()
Another very useful method when building forms which ask for such things as the user's age,
is the isWithinRange() method. It provides an easy way to check whether the input
is within a certain numeric range.
class FormValidator
{
// snip
// check whether input is within a valid numeric range
function isWithinRange($field, $msg, $min, $max)
{
$value = $this->_getValue($field);
if(!is_numeric($value) || $value < $min || $value >
$max)
{
$this->_errorList[] = array("field" => $field,
"value" => $value, "msg" => $msg);
return false;
}
else
{
return true;
}
}
}
isAlpha()
It's also possible to create more complex validation routines using PHP's built-in
support for regular expressions. This next method, isAlpha(), uses
a regular expression to test whether all the characters in the input string are
alphabetic.
class FormValidator
{
// snip
// check whether input is alphabetic
function isAlpha($field, $msg)
{
$value = $this->_getValue($field);
$pattern = "/^[a-zA-Z]+$/";
if(preg_match($pattern, $value))
{
return true;
}
else
{
$this->_errorList[] = array("field" => $field,
"value" => $value, "msg" => $msg);
return false;
}
}
}
isEmailAddress()
This ability to use regular expressions to perform data
validation comes in particularly handy when checking user-supplied email
addresses for validity - as the very cool (and very useful) class method
isEmailAddress() demonstrates:
class FormValidator
{
// snip
// check whether input is a valid email address
function isEmailAddress($field, $msg)
{
$value = $this->_getValue($field);
$pattern =
"/^([a-zA-Z0-9])+([\.a-zA-Z0-9_-])*@([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-]+)+/";
if(preg_match($pattern, $value))
{
return true;
}
else
{
$this->_errorList[] = array("field" => $field,
"value" => $value, "msg" => $msg);
return false;
}
}
}
isError()
Now we need some methods to access the error list.
The first of these is a simple little method named isError(),
which lets you
know whether or not any errors have occurred yet. Internally, all this
method does is check the size of the $_errorList array;
if the size of the array is greater than 0, it means that one or more errors have
occurred while validating the form data:
class FormValidator
{
// snip
// check whether any errors have occurred in validation
// returns Boolean
function isError()
{
if (sizeof($this->_errorList) > 0)
{
return true;
}
else
{
return false;
}
}
}
getErrorList()
Of course, all isError() does is tell you whether or not an error occurred.
To view the list of errors, you need the getErrorList() method, which returns
the current $_errorList array:
class FormValidator
{
// snip
// return the current list of errors
function getErrorList()
{
return $this->_errorList;
}
}
resetErrorList()
We will occasionally need to reset the error list to have no errors in it.
For this need we have the method resetErrorList(), which clears the $_errorList array
of all data.
class FormValidator
{
// snip
// reset the error list
function resetErrorList()
{
$this->_errorList = array();
}
}
It's a good idea to run this resetErrorList() method whenever the class is first
instantiated, which is why a call to it is in the class constructor. See the
next section.
getFormattedErrorList()
You can use the getFormattedErrorList() method to get a formatted
list of the errors.
Please note that this method first calls the class's getErrorList() method.
class FormValidator
{
// snip
// return a FORMATTED list of errors
function getFormattedErrorList()
{
$errors = $this->getErrorList();
$formattedErrorList = "<div id='fv_error_div'>\n";
$formattedErrorList .= "<p><b>The form was not submitted because one or
more error(s) occurred.</b></p> <p>Please go back and resubmit
the form after making the following changes:</p>\n";
$formattedErrorList .= "<ul>\n";
foreach ($errors as $e)
{
$formattedErrorList .= "<li>" . $e['msg'] . "</li>\n";
}
$formattedErrorList .= "</ul>\n";
$formattedErrorList .= "</div>\n";
return $formattedErrorList;
}
}
__construct()
Here is the class's constructor function:
class FormValidator
{
// snip
// constructor
// reset error list
function __construct()
{
$this->resetErrorList();
}
}
The Complete Class File
Following is the complete class definition file, FormValidatorClass.php. You can
highlight this code, copy it, and paste it into your HTML/text editor. Save it as
FormValidatorClass.php.
<?php
class FormValidator
{
//
// private variables
//
var $_errorList;
// constructor
// reset error list
function __construct()
{
$this->resetErrorList();
}
//
// methods (private)
//
// function to get the value of a variable (field)
function _getValue($field)
{
if (isset($_POST["{$field}"]))
{
return $_POST["{$field}"];
}
else
{
return "";
}
}
//
// methods (public)
//
// check whether input is empty
function isEmpty($field, $msg)
{
$value = $this->_getValue($field);
if (!is_array($value) && trim($value) == "")
{
$this->_errorList[] = array("field" => $field,
"value" => $value, "msg" => $msg);
return true;
}
else
{
return false;
}
}
// check whether input is a string
function isString($field, $msg)
{
$value = $this->_getValue($field);
if(!is_string($value))
{
$this->_errorList[] = array("field" => $field,
"value" => $value, "msg" => $msg);
return false;
}
else
{
return true;
}
}
// check whether input is a number
function isNumber($field, $msg)
{
$value = $this->_getValue($field);
if(!is_numeric($value))
{
$this->_errorList[] = array("field" => $field,
"value" => $value, "msg" => $msg);
return false;
}
else
{
return true;
}
}
// check whether input is an integer
function isInteger($field, $msg)
{
$value = $this->_getValue($field);
if(is_numeric($value))
{
if(floatval($value) != intval(floatval($value)))
{
$this->_errorList[] = array("field" => $field,
"value" => $value, "msg" => $msg);
return false;
}
else
{
return true;
}
}
else
{
$this->_errorList[] = array("field" => $field,
"value" => $value, "msg" => $msg);
return false;
}
}
// check whether input is a float
function isFloat($field, $msg)
{
$value = $this->_getValue($field);
if(is_numeric($value))
{
$castValue = (float)$value;
if(!is_float($castValue))
{
$this->_errorList[] = array("field" => $field,
"value" => $value, "msg" => $msg);
return false;
}
else
{
return true;
}
}
else
{
$this->_errorList[] = array("field" => $field,
"value" => $value, "msg" => $msg);
return false;
}
}
// check whether input is within a valid numeric range
function isWithinRange($field, $msg, $min, $max)
{
$value = $this->_getValue($field);
if(!is_numeric($value) || $value < $min || $value >
$max)
{
$this->_errorList[] = array("field" => $field,
"value" => $value, "msg" => $msg);
return false;
}
else
{
return true;
}
}
// check whether input is alphabetic
function isAlpha($field, $msg)
{
$value = $this->_getValue($field);
$pattern = "/^[a-zA-Z]+$/";
if(preg_match($pattern, $value))
{
return true;
}
else
{
$this->_errorList[] = array("field" => $field,
"value" => $value, "msg" => $msg);
return false;
}
}
// check whether input is a valid email address
function isEmailAddress($field, $msg)
{
$value = $this->_getValue($field);
$pattern =
"/^([a-zA-Z0-9])+([\.a-zA-Z0-9_-])*@([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-]+)+/";
if(preg_match($pattern, $value))
{
return true;
}
else
{
$this->_errorList[] = array("field" => $field,
"value" => $value, "msg" => $msg);
return false;
}
}
// check whether any errors have occurred in validation
// returns Boolean
function isError()
{
if (sizeof($this->_errorList) > 0)
{
return true;
}
else
{
return false;
}
}
// return the current list of errors
function getErrorList()
{
return $this->_errorList;
}
// reset the error list
function resetErrorList()
{
$this->_errorList = array();
}
// return a FORMATTED list of errors
function getFormattedErrorList()
{
$errors = $this->getErrorList();
$formattedErrorList = "<div id='fv_error_div'>\n";
$formattedErrorList .= "<p><b>The form was not submitted because one or
more error(s) occurred.</b></p> <p>Please go back and resubmit
the form after making the following changes:</p>\n";
$formattedErrorList .= "<ul>\n";
foreach ($errors as $e)
{
$formattedErrorList .= "<li>" . $e['msg'] . "</li>\n";
}
$formattedErrorList .= "</ul>\n";
$formattedErrorList .= "</div>\n";
return $formattedErrorList;
}
} // end of class
?>
The Form
Here
is a simple form which will show how to use the FormValidator class. This
is file formValidatorTestForm.php:
<!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" xml:lang="en" lang="en">
<head>
<title>Test the FormValidator Class</title>
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<style type="text/css">
.formLabel { vertical-align: top; text-align: right; padding-right: 1em; }
td, th {padding-top: 1em; }
.buttonStyle { text-align: center; }
</style>
</head>
<body>
<div style='width: 700px; border: 1px solid gray; border-radius: 2em; margin: 0 auto; padding:1em; font-family: Arial, sans-serif;'>
<form action="formValidatorAction.php" method="post">
<table>
<tr>
<th class="formLabel">Name:</th>
<td><input type="text" name="name" size="15" /></td>
</tr>
<tr>
<th class="formLabel">Telephone Number:</th>
<td><input type="text" name="phone" size="20" /></td>
</tr>
<tr>
<th class="formLabel">Age:</th>
<td><input type="text" name="age" size="3" maxlength="3" /></td>
</tr>
<tr>
<th class="formLabel">Sex:</th>
<td><input type="radio" name="sex" value="m" />Male
<input type="radio" name="sex" value="f" />Female</td>
</tr>
<tr>
<th class="formLabel">Favorite sandwich type:</th>
<td><select name="stype">
<option value="">-select one-</option>
<option value="1">Thin crust</option>
<option value="2">Thick crust</option>
<option value="3">Toasted</option>
</select>
</td>
</tr>
<tr>
<th class="formLabel">Favorite sandwich filling:</th>
<td><input type="checkbox" name="sfill[]" value="BLT" />Bacon, lettuce tomato
<input type="checkbox" name="sfill[]" value="EC" />Egg and cheese
<input type="checkbox" name="sfill[]" value="PBJ" />Peanut butter and jelly</td>
</tr>
<tr>
<th class="formLabel">How much you would pay for the above sandwich:</th>
<td><input type="text" name="price" size="10" /></td>
</tr>
<tr>
<th class="formLabel">Give us your e-mail address, please:</th>
<td><input type="text" name="email" size="40" /></td>
</tr>
<tr>
<td colspan="2" class="buttonStyle"><input type="submit" name="submit" value="Send Your Information" /></td>
</tr>
</table>
</form>
</div>
</body>
</html>
The Action Page
When this form is submitted, the PHP script formValidatorAction.php will
receive the form variables. The script formValidatorAction.php
will first need to verify that the data entered into the form is acceptable,
and it uses the FormValidator class to do so.
The script then does something with the data (for example, it INSERTs the data into a MySQL
database):
Please note that this action page is extending the original
class to have a new function, isPhone(). This is one of the powerful
features of objects in PHP.
<!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" xml:lang="en" lang="en">
<head>
<title>Test the FormValidator Class -- Action Page</title>
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<style type="text/css">
.formLabel { vertical-align: top; text-align: right; padding-right: 1em; }
td, th {padding-top: 1em; }
.buttonStyle { text-align: center; }
</style>
</head>
<body>
<?php
require("includes/isSQLInject.php");
require("includes/CheckURLandFORMscope.php");
// include class
include("FormValidatorClass.php");
class myValidator extends FormValidator
{
// check whether input is a valid phone number
function isPhone($field, $msg)
{
$value = $this->_getValue($field);
$pattern = "/^\(?\d{3}\)?(\s|\.|-)?\d{3}(\s|-|\.)?\d{4}$/";
if(preg_match($pattern, $value))
{
return true;
}
else
{
$this->_errorList[] = array("field" => $field,
"value" => $value, "msg" => $msg);
return false;
}
}
}
// instantiate object
$fv = new myValidator();
// perform some validations:
$fv->isEmpty("name", "Please enter a name");
$fv->isEmpty("phone", "Please enter your phone number.");
$fv->isPhone("phone", "Please enter a valid phone number in format NNN-NNN-NNNN.");
//$fv->isNumber("age", "Please enter a valid age");
$fv->isInteger("age", "Please enter an age which is a whole number.");
$fv->isWithinRange("age", "Please enter an age within the numeric range 1-99", 1, 99);
$fv->isEmpty("sex", "Please enter your sex");
$fv->isEmpty("stype", "Please select one of the listed sandwich types");
$fv->isEmpty("sfill", "Please select one or more of the listed sandwich fillings");
//$fv->isNumber("price", "Please enter a numeric price.");
$fv->isFloat("price", "Please enter a price which is a decimal number.");
$fv->isEmailAddress("email", "Please enter a valid e-mail address.");
if ($fv->isError())
{
echo " <div id='error_container'>\n";
echo $fv->getFormattedErrorList();
echo " <a class='overlap_bottom' href='' onclick='history.back();'>Try again </a>\n";
echo " </div>";
}
else
{
// do something useful with the data
echo "<div style='width: 700px; border: 1px solid gray; border-radius: 2em; margin: 0 auto; padding:1em; font-family: Arial, sans-serif;'>\n";
echo "<h4>Data OK</h4>\n";
echo "<pre>\n";
print_r($_POST);
echo "</pre>\n";
echo "</div>\n";
}
?>
</body>
</html>
FormValidator Class Documentation
First, here is a portion of the stylesheet that formats the error information that
is returned by the method getFormattedErrorList():
#error_container
{
position: absolute;
left: 120px;
top: 170px;
}
.overlap_bottom
{
position: relative;
left: 1em;
top: -1.6em;
}
#fv_error_div
{
z-index: 3;
width: 700px;
border: 1px solid gray;
border-radius: 2em;
margin: 0 auto;
padding:1em;
font-family: Arial, sans-serif;
background-color: #FDD;
}
And now a listing of the methods in the FormValidator
Class can be found here.