How To HTML Form With PHP/JS/Captcha Validation - The Ultimate Guide!
Here is a working Demo »
Download source ZIP file »
How to build a html form with PHP (server side), JS (client side), a simple but effective captcha, that validates all the form fields, and secures your server from hijacking spam bots, that functions seamlessly?! This whole question is one BIG puzzle is it not? Well call me the "The Puzzle Man", because I just made it very easy and put all the peices of the puzzle together in one small nicely zipped up package. A special thanks to Sitepoint forum members Pullo and ScallioXTX for helping me work out the PHP/JS kinks. And here are 4 other demos of different ways to display the JS validation errors.
Awsesome Form Attributes!
- Simple directions (relatively)
- Clean HTML/CSS code
- Easily editable PHP formmail code with detailed comments
- Simple but strong and effective PHP backend protection/validation
- JS (client side) eye candy validation
- Finally an easy but effective captcha
- Captcha displays and validates random numbers 1-5 (e.g. 2+3, 1+4, etc)
- Confirmation page
- If JS off PHP error page
- Nicely formated email
- Works in all browsers IE7+
DIRECTIONS...
Step 1: Create 7 Pages
- html-form-page.php (AKA the page that holds your html form)
- formmail-page.php (AKA the page that holds your PHP form processing code)
- validate-captcha-page.php (AKA the page that holds the PHP that helps validate the captcha)
- error-page.php (AKA the page that holds the error message if JS is bypassed)
- confirmation-page.php (AKA the page that displays the successful form submission message)
- jQuery-page.js (AKA the page that holds jQuery v1.8.3)
- jQuery-validation-page.js (AKA the page that holds jQuery Validation Plugin v1.10.0)
Step 2: Download JS dependencies
jQuery v1.8.3
jQuery Validation Plugin v1.10.0
Step 3: html-form-page.php code
Note: the PHP above the DOCTYPE and the PHP in the Captcha label is whats needed to enable the captcha to work. The JS is what's needed for the validation plugin to work. If you want messages to appear instead of just the red outline, remove label.error display none in the CSS and add the wanted messages to the "messages" section in the JS.
<?php session_start(); if (!isset($_SESSION['num1']) && !isset($_SESSION['num2'])) { $_SESSION['num1'] = rand(1,5); $_SESSION['num2'] = rand(1,5); } ?> <!DOCTYPE html><html><head><meta charset="UTF-8"> <title>HTML Form Page</title> <style type="text/css"> /* --- form css --- */ form { width:400px; } input, textarea, label { display:inline-block; margin:10px 5px; width:150px; vertical-align:middle; padding:4px; } input, textarea { border:1px solid #666; box-shadow:0 0 4px #666; border-radius:5px; } label { text-align:right; } #submit { margin-left:177px; width:160px; background:#ddd; cursor:pointer; } /* --- error css --- */ input.error, textarea.error { border:1px solid red; box-shadow:0 0 4px red; } label.error { display:none !important; } input.error, textarea.error { -moz-animation:glow ease-in infinite alternate 500ms; -webkit-animation:glow ease-in infinite alternate 500ms; -ms-animation:glow ease-in infinite alternate 500ms; animation:glow ease-in infinite alternate 500ms; } @-moz-keyframes glow {0%{box-shadow:0 0 4px red;}100%{box-shadow:0 0 9px red;}} @-webkit-keyframes glow {0%{box-shadow:0 0 4px red;}100%{box-shadow:0 0 9px red;}} @-ms-keyframes glow {0%{box-shadow:0 0 4px red;}100%{box-shadow:0 0 9px red;}} @keyframes glow {0%{box-shadow:0 0 4px red;}100%{box-shadow:0 0 9px red;}} </style> </head> <body> <form method="post" action="how-to-html-form-with-php-js-captcha-validation-formmail.php"> <label for="name">Name</label> <input type="text" id="name" name="name" placeholder="Name"> <br> <label for="email">Email</label> <input type="text" maxlength="50" id="email" name="email" placeholder="Email"> <br> <label for="comments">Comments</label> <textarea id="comments" name="comments" rows="1" cols="1" placeholder="Comments"></textarea> <br> <label for="captcha"><?php echo $_SESSION['num1']; ?>+ <?php echo $_SESSION['num2']; ?>?</label> <input type="text" id="captcha" name="captcha" placeholder="Captcha"> <br> <input type="submit" name="submit" value="Submit" id="submit"> </form> <script src="jquery/jQuery1.8.3.js"></script> <script src="jquery/jQuery.validation.1.10.0.js"></script> <script type="text/javascript"> $(document).ready(function() { $.validator.addMethod("nourl", function(value, element) { return !/http://|www.|link=|url=/.test(value); }, "No URL's"); $("form").validate({ rules: { name: { required: true }, email: { required: true, email: true }, comments: { required: true, minlength: 4, nourl: true }, captcha: { required: true, remote: { url: "validation-captcha-page.php", type: "post" } } }, messages: { name: "", email: "", comments: "", captcha: "" } }); }); </script> </body></html>
Step 4: formmail-page.php code
<?php // ======================================================================= // NOTE: In the 3 places below that are wrapped in comments exactly like // the ones wrapping this sentence INSERT YOUR specific information // Author: Eric Watson @ http://www.visibilityinherit.com // ======================================================================= // Prevent browser cache header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); header("Cache-Control: no-store, no-cache, must-revalidate"); header("Cache-Control: post-check=0, pre-check=0", false); header("Pragma: no-cache"); // Remove headers function remove_headers($string) { $headers = array( "/to\:/i", "/from\:/i", "/bcc\:/i", "/cc\:/i", "/Content\-Transfer\-Encoding\:/i", "/Content\-Type\:/i", "/Mime\-Version\:/i" ); if (preg_replace($headers, '', $string) == $string) { return $string; } else { die(''); } } // Separate headers by either \r\n or \n to ensure email sends properly $uself = 0; $headersep = (!isset( $uself ) || ($uself == 0)) ? "\r\n" : "\n" ; // ======================================================================= // Insert your information and correct link paths here $mailto = 'your@email.com' ; $from = "Your Business Name Formmail" ; $formurl = "formmail-page.php" ; $errorurl = "errorpage.php" ; $thankyouurl = "confirmation-page.php" ; // ======================================================================= // ======================================================================= // Add or remove your specific Form variables here $name = remove_headers($_POST['name']); $email = remove_headers($_POST['email']); $comments = remove_headers($_POST['comments']); $spam = remove_headers($_POST['captcha']); $http_referrer = getenv( "HTTP_REFERER" ); // ======================================================================= // ======================================================================= // Un-comment if you want to add/clean PHONE to form // if (preg_match("{[A-Za-z]}", $phone)) // { // header( "Location: $errorurl" ); // exit ; // } // ======================================================================= // If name or email contain carriage returns or new line characters stop execution and direct to errorurl if ( ereg( "[\r\n]", $name ) || ereg( "[\r\n]", $email ) ) { header( "Location: $errorurl" ); exit ; } // Clean Email - if empty ignore - if value in form input clean if (!empty($email) && !preg_match("/^[A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i",$email)) { header( "Location: $errorurl" ); exit ; } // Clean Comments if (get_magic_quotes_gpc()) { $comments = stripslashes( $comments ); } // Clean Comments - max 1250 characters if (strlen($comments) > 1250) { $comments=substr($comments, 0, 1250).'...'; } // Clean Comments - no URL's if (preg_match("{link=}", $comments) || preg_match("{url=}", $comments) || preg_match("{http://}", $comments)) { header( "Location: $errorurl" ); exit ; } // Make Name, Email, and Comments required before form submission if (empty($name) || empty($email) ||empty($comments)) { header( "Location: $errorurl" ); exit ; } // Clean Captcha: random numbers 1 through 5 (1+3, 4+2, 5+3, etc) session_start(); if (!isset($_SESSION['num1']) || !isset($_SESSION['num2'])) { // no known session. cannot validate captcha header( "Location: $errorurl" ); exit; } $sum = (int)$_SESSION['num1'] + (int)$_SESSION['num2']; if (isset($_POST['captcha']) && (int)$_POST['captcha'] !== $sum) { // captcha given but incorrect header( "Location: $errorurl" ); exit; } else { // captcha correct, show a new one next time unset($_SESSION['num1'], $_SESSION['num2']); } // Send Message $message = "This message was sent from:\n" . "$http_referrer\n\n" . // ======================================================================= // Add or remove your specific Form variables here "Name: $name\n\n" . "Email: $email\n\n" . "Comments: $comments\n\n" . // ======================================================================= "Captcha: $captcha\n\n" . "\n\n------------------------------------------------------------\n" ; mail($mailto, $from, $message, "From: \"$name\" <$email>" . $headersep . "Reply-To: \"$name\" <$email>" . $headersep ); header( "Location: $thankyouurl" ); exit ; ?>
Step 5: validate-captcha-page.php code
This is the PHP page that is called by the "remote" rule in the validation plugin to help validate the captcha.
<?php session_start(); if (!isset($_SESSION['num1']) || !isset($_SESSION['num2'])) { exit('"Unknown session"'); } $sum = (int)$_SESSION['num1'] + (int)$_SESSION['num2']; if (isset($_POST['captcha']) && (int)$_POST['captcha'] === $sum) { exit('true'); } exit('false'); ?>
Step 6: error-page.php code
This is the error page that is shown if JS is off and PHP validates the form instead.
<!DOCTYPE html><html><head><meta charset="UTF-8"> <title>Error Page</title> </head> <body> <h1>Error</h1> <p>Oops sorry, there was an error in the information you entered. You either failed to fill in all of the required<br> information, or made a mistake while typing. You may try again by using the back button in your browser.</p> </body></html>
Step 7: confirmation-page.php code
This is the messages displayed to the user after a successful form submission.
<!DOCTYPE html><html><head><meta charset="UTF-8"> <title>Confirmation Page</title> </head> <body> <h1>Thank you! Message recieved. We will get back to you shortly...</h1> </body></html>
DONE! Message in your email box looks like this...
This message was sent from http://www.your-webpage.com Name: Eric Watson Email: eric@gmail.com Comments: Hello Eric, this tutorial is amazing! Captcha: 8