📖 PHP Sanitizing and Validating Form Data
Validation is an important part of form processing. Whenever a user enters data via a form, we want to make sure that it is valid for security and data integrity.
- security
- make sure that hackers cannot enter malicious code that could compromise the system or data
- data integrity
- make sure that the data being entered is accurate and meets the data requirements of the application. This is especially important if the data is being used to update a database.
The advantage is to be able to redisplay the form with the user input (see sticky form fields below) along with error messages if there is a problem with the data.
We will be looking at additional functions and methods to validate form data in the other competencies in this section, but as a starting point we will look at some simple validation functions and sanitizing functions that should be used on all form data.
Sanitizing Data
The data submitted with the form must be validated and sanitized for use in the PHP program. If not, the application could be compromised by a variety of site attacks. The data must first be sanitized to remove malicious code and prepare the data for further processing.
When processing user entered data, there may be some data they enter that can interfere with the proper execution of the script or cause problems in the database. For example, a quote or double-quote may indicate the end of a string, when it is really just part of user input. A semi-colon could indicate the end of a SQL statement rather then being part of the data inside of a data field. HTML tags may cause your pages to not display properly. PHP includes some built-in functions that can be used to sanitize user input before using it in the code:
- htmlspecialchars(string)
- converts certain HTML characters ( < > " ' & ) into entities.
- htmlentities(string)
- converts all HTML characters into entities.
- strip_tags(string)
- removes all HTML and PHP tags.
- html_entity_decode(string)
- converts HTML entities into HTML code.
- urlencode(string)
- encodes the string to proper URL syntax.
- urldecode(string)
- decodes the string from proper URL syntax to plain text.
Data Validation
Once the form data is sanitized, it must be validated for completion and acceptable content. If a form control (field) is not filled out properly by the user, the form must be redisplayed to the user with the valid content filled out by the user in the form fields. These are called sticky form fields. Finally, the user must have the appropriate response from the server to progress through the application.
Here are some common types of validation and data preparation that you may want to include in your scripts that update a database to make sure your data is clean and valid.
- Remove excess white space (trim).
- Make sure data is the right length (not too long for the field or too short for the requirements) (strlen).
- Make sure required fields are present (empty, isset).
- Test the data for the proper data format (numeric, date, boolean).
- Test for specific values: (true/false, numeric range, AM/PM, etc.).
- Pattern matching (email address, credit card number, social security number, phone number, etc.) (regular expressions).
Validation Functions
- empty(testval)
- returns TRUE if the testval contains an empty string. Used to make sure form text boxes have been filled out.
(Note: spaces are characters so a variable that contains spaces will return FALSE) - isset(testval)
- returns TRUE if the testval variable exists, even if it is equal to 0 or an empty string.
Used to validate non-text elements like checkboxes and radio buttons or see if a form has been submitted. - is_numeric(testval)
- returns TRUE if testval has a valid numerical value. Used to verify numeric input.
Sticky Form Fields
When validating data, we typically will set a flag (boolean variable) to track if all the data is valid. We will initialize the variable to false to load the original form, gut then to true when processing the submitted data assuming it is all valid. Then if we find an error, we set it back to false to trigger loading the form and redisplaying with the user entered data. After all validation is complete, we will test the variable to see if we need the user to correct any information before continuing the application. If the user data is not correct, we send the form back to the user with their most recently entered data and any warning messages needed to prompt the user to enter the correct information.
- Redisplay user entered values in a form so they don't have to re-input the values.
- Especially helpful for error handling and validation.
- In value clause in html, add php code to print the variable.
<input type="text" id="lastname" value="$lastname" />$errorMessage
- Must initialize all variables to null or empty strings for the first time through the form.
- For radio buttons, selection lists, and checkboxes, test the value to see if it matches and add the 'checked' or 'selected' option.
Example
The updated example with some simple validation and sticky form fields.
<?php
// set the sticky field to empty or NULL to avoid error messages
$artist = NULL;
$album = NULL;
$rdate = NULL;
$type = NULL;
$downloadChecked = NULL;
$cdChecked = NULL;
// set error messages to empty or NULL
$artistError = NULL;
$albumError = NULL;
$rdateError = NULL;
$typeError = NULL;
// set the validation flag to load the form
$valid = false;
// check to see if the form has been submitted if so process the form data.
if (isset($_POST['submit'])) {
// change the validation flag to assume data integrity
$valid = true;
// retrieve the values from the form. use htmlspecialchars to avoid security issues
$artist = htmlspecialchars($_POST['artist']);
if (empty($artist)) {
$artistError = "<span class='error'>You must enter an artist</span>";
$valid = false;
}
$album = htmlspecialchars($_POST['album']);
if (empty($album)) {
$albumError = "<span class='error'>You must enter an album</span>";
$valid = false;
}
$rdate = htmlspecialchars($_POST['rdate']);
// since release date is a year, test to make sure it is numeric
if (!is_numeric($rdate)) {
$rdateError = "<span class='error'>Release date must be numeric</span>";
$valid = false;
}
// since type is a radio button, we will use isset to test if the user selected one of the options.
if (isset($_POST['type'])) {
// if set, get the type. No need for htmlspecialchars here, since the user can only select a value we provided.
$type = $_POST['type'];
if ($type == "download") {$downloadChecked = "checked";}
if ($type == "cd") {$cdChecked = "checked";}
} else {
$typeError = "<span class='error'>Please select a type</span>";
$valid = false;
}
}
// if the data is valid, display the values on the page
if ($valid) {
echo "<p>You entered the following values:";
echo "<br>Artist: $artist";
echo "<br>Album: $album";
echo "<br>Release date: $rdate";
echo "<br>Type: $type";
} else {
echo <<<EOD
<fieldset>
<legend> Example Form </legend>
<form method="post" action="form.php">
<p>
<label for="artist">Artist</label>$artistError
<input type="text" name="artist" id="artist" value="$artist">
</p>
<p>
<label for="album">Album</label>$albumError
<input type="text" name="album" id="album" value="$album">
</p>
<p>
<label for="rdate">Release date</label>$rdateError
<input type="text" name="rdate" id="rdate" value="$rdate">
</p>
<p>
<input type="radio" name="type" id="typecd" value="cd" $cdChecked>
<label for="typecd">CD</label>
<input type="radio" name="type" id="typedl" value="download" $downloadChecked>
<label for="typedl">Download</label>$typeError
</p><br />
<p>
<input type="submit" name="submit" value="Add Album">
</p>
</form>
</fieldset>
EOD;
}
HTTP Header
Sends information between server and client (browser) using header('Location: url');
- Transfers the user to the page specified by the url.
- Must be called before any output is sent to the browser.
- Usually followed by
exit();
to cancel execution of the script. - May use querystring to pass information to the new program.
Example
In this example, instead of displaying the information on the page, we will pass it to another php page if the data is valid.
<?php
// set the sticky field to empty or NULL to avoid error messages
$artist = NULL;
$album = NULL;
$rdate = NULL;
$type = NULL;
$downloadChecked = NULL;
$cdChecked = NULL;
// set error messages to empty or NULL
$artistError = NULL;
$albumError = NULL;
$rdateError = NULL;
$typeError = NULL;
// set the validation flag
$valid = false;
// check to see if the form has been submitted if so write out the data.
if (isset($_POST['submit'])) {
// change the validation flag to assume data integrity
$valid = true;
// retrieve the values from the form. use htmlspecialchars to avoid security issues
$artist = htmlspecialchars($_POST['artist']);
if (empty($artist)) {
$artistError = "<span class='error'>You must enter an artist</span>";
$valid = false;
}
$album = htmlspecialchars($_POST['album']);
if (empty($album)) {
$albumError = "<span class='error'>You must enter an album</span>";
$valid = false;
}
$rdate = htmlspecialchars($_POST['rdate']);
// since release date is a year, test to make sure it is numeric
if (!is_numeric($rdate)) {
$rdateError = "<span class='error'>Release date must be numeric</span>";
$valid = false;
}
// since type is a radio button, we will use isset to test if the user selected one of the options.
if (isset($_POST['type'])) {
// if set, get the type. No need for htmlspecialchars here, since the user can only select a value we provided.
$type = $_POST['type'];
if ($type == "download") {$downloadChecked = "checked";}
if ($type == "cd") {$cdChecked = "checked";}
} else {
$typeError = "<span class='error'>Please select a type</span>";
$valid = false;
}
}
// if the data is valid, display the values on the page
if ($valid) {
header("Location: add.php?album=$album&artist=$artist&rdate=$rdate&type=$type");
exit();
} else {
echo <<<EOD
<fieldset>
<legend> Example Form </legend>
<form method="post" action="form.php">
<p>
<label for="artist">Artist</label>$artistError
<input type="text" name="artist" id="artist" value="$artist">
</p>
<p>
<label for="album">Album</label>$albumError
<input type="text" name="album" id="album" value="$album">
</p>
<p>
<label for="rdate">Release date</label>$rdateError
<input type="text" name="rdate" id="rdate" value="$rdate">
</p>
<p>
<input type="radio" name="type" id="typecd" value="cd" $cdChecked>
<label for="typecd">CD</label>
<input type="radio" name="type" id="typedl" value="download" $downloadChecked>
<label for="typedl">Download</label>$typeError
</p><br />
<p>
<input type="submit" name="submit" value="Add Album">
</p>
</form>
</fieldset>
EOD;
}