Written by Brian Cray on September 18th, 2009
Since I've been working on my CMS the past few days I've been on a little PHP trip. I'll probably be writing a few PHP posts over the next week or so, intermingled with other topics of course.
This tutorial should help you build smarter web forms with PHP and save you a ton of time.
Let's start with web form sanitization.
Sanitize all user input through a standard PHP function
User input sometimes has unnecessary whitespace, so we'll trim that off. We'll also check if magic_quotes_gpc is automatically adding backslashes to user input and remove as necessary.
$hasgpc = get_magic_quotes_gpc();
foreach($_POST as $field => $value)
{
$value = trim($value);
if($hasgpc)
{
$value = stripslashes($value);
}
$filtered_post[$field] = $value;
}
Add user input verification
To verify user input, we'll first add meta information about each web form input field to its name property.
Adding field properties to each field on the web form display side
Notice the use of the underline to separate a field's properties in the name.
<form method="post" action="myscript.php">
<input type="text" name="username_required_alphanumeric">
<input type="text" name="email_required_emailaddress">
</form>
Verifying form input using on the web form submission side
$hasgpc = get_magic_quotes_gpc();
foreach($_POST as $field => $value)
{
/* first we extract the actual intended field name */
$fieldinfo = explode('_', $field); // turn the posted field name into an array of properties
$field = array_shift($fieldinfo); // take the first element as the intended field name
/* do the standard stuff we discussed above */
$value = trim($value);
if($hasgpc)
{
$value = stripslashes($value);
}
$filtered_post[$field] = $value;
/* new stuff to verify user input based on $fieldinfo */
if(array_search('required', $fieldinfo) && empty($value))
{
$error = TRUE;
}
if(array_search('emailaddress', $fieldinfo) && !preg_match('|^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$|i', $value))
{
$error = TRUE;
}
if(array_search('alphanumeric', $fieldinfo) && preg_match('|[^a-z0-9]|i', $value))
{
$error = TRUE;
}
}
/* if there were errors in the web form, send the user back to make changes */
if($error)
{
header('Location: ' . $_SERVER['HTTP_REFERER']);
exit;
}
/*
at this point the form has been cleaned and validated.
reference the fields with $filtered_post, such as $filtered_post['username']
*/
Things to consider about this method
- This tutorial is supposed to emphasize web form sanitization and validation with PHP. You can greatly improve the user feedback on errors versus what I've used above. In fact I compell you to for the user's sake. One way to do this is to pass the errors back in the session and display them above the web form. I'd also recommend sending back the submitted values so the user doesn't have to retype them.
- While this method kicks ass, it has its limitations. The one I thought of is that a field cannot be named the same thing as a filter. For example,
<input type="text" name="emailaddress_required_emailaddress">wouldn't work. - Starting with PHP 5.2.0 you can use filter_var() to validate fields instead of regular expressions as used above.
- A few people have pointed out that this is not the most secure method of form validation because someone can hack the form field names. Keep that in mind if you decide to use this method of form validation.