Advanced PHP Form Validation

Last year I wrote an article in how to implement basic validation for a form with PHP. I decided to re-look at this and improve what I did in that article. This time we are going to make a more advanced PHP form that is more responsive and effective.

This PHP sample code has many advantages over the previous article. Not only that, but for the most part it is easier to implement with more complexed forms where you need more than basic validation.

Requirements

Below are the requirements for the code included in this PHP form tutorial:

JavaScript has become standard in browsers, which makes client side form validation user friendly before submitting the form. In fact, in most cases, it is the standard for form validation on the web.

With that said, I do not recommend depending on client side validation for your forms…mainly in defending against hackers and bots. But most people who use your form should have JavaScript enabled.

You can view a demo of the PHP form in action. You will not only see the standard validation (email, phone, and required fields), but we also take it a step further by validating check boxes. If the visitor checks the newsletter option, they must then check two topics before the form can be submitted (in the same way, you can do something like this with radio buttons). If there are errors in the form, and those errors are corrected, they will immediately disappear.

I took an example from the jQuery validation documentation and tweaked it a little bit to fit the form, for this PHP tutorial.

Form HTML Page

Below is the html for the page where the form will sit.

 <html> <head> <script type="text/javascript" src="js/jquery-1.5.2.min.js"></script> <script type="text/javascript" src="js/jquery.validate.min.js"></script> <script type="text/javascript" src="js/additional-methods.min.js"></script>  <style type="text/css"> label {  	float: left;  	padding-right:10px; } label.error {  	float: none;  	color: red;  	padding-left: .5em;  	vertical-align: top;  } p {  	clear: both;  } .gray {  	/*color: gray;*/ 	display: none; } #newsletter_topics label.error { 	display: none; 	padding-left: 0px; } </style>   <script type="text/javascript"> $  (document).ready(function(){ 	// validate signup form on keyup and submit 	$  ("#signupForm").validate({ 		rules: { 			firstname: "required", 			lastname: "required", 			email: { 				required: true, 				email: true 			}, 			phone: { 				required: true, 				phoneUS: true 			}, 			agree: "required", 			'topic[]': { 				required: "#newsletter:checked", 				minlength: 2 			} 		}, 		messages: { 			firstname: "Please enter your firstname.", 			lastname: "Please enter your lastname.", 			email: "Please enter a valid email address.", 			phone: "Please specify a valid phone number.", 			agree: "Please accept our policy." 		} 	}); 	 	//code to hide topic selection, disable for demo 	var newsletter = $  ("#newsletter"); 	 	// newsletter topics are optional, hide at first 	var inital = newsletter.is(":checked"); 	var topics = $  ("#newsletter_topics")[inital ? "removeClass" : "addClass"]("gray"); 	var topicInputs = topics.find("input").attr("disabled", !inital); 	 	// show when newsletter is checked 	newsletter.click(function() { 		topics[this.checked ? "removeClass" : "addClass"]("gray"); 		topicInputs.attr("disabled", !this.checked); 	}); }); </script>   </head> <body>  <form id="signupForm" method="POST" action="processform.php">  	<fieldset>  		<legend>Signup Form</legend>  		<p>  			<label for="firstname">*Firstname:</label>  			<input id="firstname" name="firstname" />  		</p>  		<p>  			<label for="lastname">*Lastname:</label>  			<input id="lastname" name="lastname" />  		</p>  		<p>  			<label for="email">*Email:</label>  			<input id="email" name="email" />  		</p>  		<p>  			<label for="phone">*Phone Number:</label>  			<input id="phone" name="phone" />  		</p>  		 		<p>[ENTER POLICY HERE]</p> 		<p>  			<label for="agree">*Do you agree to our policy?</label>  			<input type="checkbox" class="checkbox" id="agree" name="agree" />  		</p> 		 		<p>  			<label for="newsletter">Would you like to receive our newsletter?</label>  			<input type="checkbox" class="checkbox" id="newsletter" name="newsletter" />  		</p>  		<fieldset id="newsletter_topics">  			<legend>Topics (select at least two) - note: would be hidden when newsletter isn't selected, but is visible here for the demo</legend>  			<label for="topic_marketflash">  				<input type="checkbox" id="topic_marketflash" value="marketflash" name="topic[]" />  				Marketflash 			</label>  			<label for="topic_fuzz">  				<input type="checkbox" id="topic_fuzz" value="fuzz" name="topic[]" />  				Latest fuzz 			</label>  			<label for="topic_digester">  				<input type="checkbox" id="topic_digester" value="digester" name="topic[]" />  				Mailing list digester 			</label>  			<label for="topic[]" class="error"><br /><br />Please select at least two topics you'd like to receive.</label>  		</fieldset>  		<p>  			<input class="submit" type="submit" value="Submit"/>  		</p>  	</fieldset>  </form>   </body> </html>

One thing you will notice is that there is no PHP code on this page. You will also notice that jQuery is used heavily. In the head tag we define which fields are required and the error messages to display if the field is not entered correctly. This is the largest improvement over the last form example, since the client side error handling is immediate and it displays the errors without posting the form. There was no client side validation in the previous PHP form article.

If you are not familiar in working with jQuery, I highly recommend going through some basic jQuery examples. The bundled code I provide at the end of this PHP tutorial includes the jQuery files necessary in making this example work.

PHP: Process the Form

Since jQuery is JavaScript, if the visitor has JavaScript disabled, the validation on this page will not work and the form will be posted. With this in mind, we still need to do server side validation. I took the code that was used in the previous tutorial, and improved it for this example.

 <?php  /*  * BEGIN CONFIG  */  // The page you want the user to be redirected if there are no errors. $  thankYouPage = 'thanks.html';  // Define which values we are to accept from the form. If you add additional  // fields to the form, make sure to add the form name values here. $  allowedFields = array( 	'firstname',  	'lastname', 	'email', 	'phone', 	'agree', 	'newsletter', 	'topic', );  // Specify the required form fields. The key is the field name and the value  // is the error message to display. $  requiredFields = array( 	'firstname' => 'First name is required.',  	'lastname' => 'Last name is required.', 	'email' => 'Email address is required.', 	'phone' => 'Phone number is required.', 	'agree' => 'You must agree with our policy.', );  // Note: Since we are requiring two topics to be checked if they want to receive  // our newsletter, we need to implement custom code.  /*  * END CONFIG  */   /*  * Since we are doing javascript error checking on the form before the form gets submitted,   * the server side check is only a backup if the user has javascript disabled. Since this   * is unlikely, we are displaying the server side errors on a separate page of the form.  *   * The more practical purpose of server side checking (in this case) is to prevent hackers from exploiting   * your PHP processing code.  */   /*  * BEGIN FORM VALIDATION  */  $  errors = array();  // We need to loop through the required variables to make sure they were posted with the form. foreach($  requiredFields as $  fieldname => $  errorMsg) { 	if(empty($  _POST[$  fieldname])) 	{ 		$  errors[] = $  errorMsg; 	} }  // Loop through the $  _POST array, to create the PHP variables from our form. foreach($  _POST AS $  key => $  value) {     // Is this an allowed field? This is a security measure.     if(in_array($  key, $  allowedFields))     {         $  {$  key} = $  value;     } }  // Code to validate the newsletter topic checkboxes if(!empty($  _POST['newsletter'])) { 	// They checked the newsletter checkbox...make sure they  	// checked at least two topics. 	if(count($  _POST['topic']) < 2) 	{ 		$  errors[] = "In order to receive our newsletter, you must check at least two topics."; 	} }  /*  * END FORM VALIDATION  */   // Were there any errors? if(count($  errors) > 0) {     $  errorString .= '<ul>';     foreach($  errors as $  error)     {         $  errorString .= "<li>$  error</li>";     }     $  errorString .= '</ul>';       // display the errors on the page     ?>     <html>     <head>     <title>Error Processing Form</title>     </head>     <body>     <h2>Error Processing Form</h2>     <p>There was an error processing the form.</p>     <?php echo $  errorString; ?>     <p><a href="index.php">Go Back to the Form</a></p>     </body>     </html>     <?php  } else {     // At this point you can send out an email or do whatever you want     // with the data...       // each allowed form field name is now a php variable that you can access       // display the thank you page     header("Location: $  thankYouPage"); } ?>

A configuration area was added to the beginning of the file. Notice that in this code, if there is are no errors processing the form, we display the errors on this page instead of the previous form. This does several things:

1. Since the majority of people will have JavaScript enabled, the server side form validation is only meant as a backup and to prevent hackers from trying to exploit the form. So displaying errors on a blank page should suffice in this case. With that said, there may be times were going back to the form and pre-populating the fields makes sense.

2. This simplifies things. We don’t have to use PHP on the form html page at all.

I also do not use the short tag version of calling PHP for compatibility.

You can download all of the PHP Form Code, which includes the required JavaScript files.

Montana Programmer

[plinker]

HTML

AdvancedFormValidation

Leave a Reply

Your email address will not be published. Required fields are marked *