Page 1 of 1

Validating forms with PHP Validating an input and displaying error messages based on what's Rate Topic: -----

#1 spearfish  Icon User is offline

  • Monkey in Training
  • member icon

Reputation: 10
  • View blog
  • Posts: 746
  • Joined: 10-March 08

Posted 15 March 2008 - 03:41 AM

Hey guys---

This is my first shot at a tutorial, so it'll probably be a rough ride. Try to bear with me, and correct me when needed. It's also pretty late, so forgive any grammatical errors / typos (although I would appreciate you pointing them out). I have tested this script, it works. B)

In this tutorial I'll show you how to validate forms using PHP. Sure, you can validate forms using Javascript. It's a whole lot faster. But what happens if the use simply turns Javascript off? In that case, maybe you need to make the submit button disabled, unless the form checks out alright. But then what if the user has no Javascript support at all? And, what if you hit a smart bugger who simply copies your HTML form, minus the Javascript (see "formhack.html").

Javascript is still a nice validation tool, especially for giving people on-the-fly feedback. But if you rely solely on it, you're screwed. I'll show you how to add the PHP part:

What you need:
  • A PHP enabled web server
  • Patience
~~~

Let's suppose that this page is receiving information via POST from a form. What we want to do is check to see if it meets various requirements, and then telling the user exactly what's wrong. If there's one thing wrong with it, they see one error message. Thirty things wrong? Thirty error messages.

<?php
$information = $_POST['formdata'];



There are several things we can do to validate $information, all of which use PHP's ereg function. Bene notate that this is a case sensitive function. For most validation, you probably want case insensitivity, unless you're going to be a real jerk and stop them for not capitalizing their name. Thus, I will be using the eregi function throughout the tutorial, a duplicate of ereg except with case insensitivity. I'll also cast any boolean values to integers. You don't have to, I just dislike dealing with booleans.

The basic format for the custom - error - validation system is to pass the string in question through several tests, what I like to call the gauntlet. Then, if it passes every test, code executes. Otherwise, the code digs deeper, and using a series of "if" statements (the crucial part here is to use simply if ( ) { rather than else if ( ) {) displays what all is wrong with the information.
~~~

I'll first go through as if $information is containing a string that should contain numbers and letters, for something like a username, or an address. Then I'll go into the specific examples of phone numbers and email addresses. I won't be covering captchas, but there's a snippet here.

First, let's make sure that $information only contains numbers, letters, or any other characters you want to throw in (I mean, if you like people creating usernames such as "%@$7 #(h)".... ). What we need to do is search for any character that isn't on the list of accepted characters. If we simply search for something on the list, the aforementioned repugnant username passes, because it does contain an "h".
$validate1 = eregi('[^a-z0-9]', $information);
$validate1 = (int)$validate1;



This function's syntax is eregi('string to search for', 'string to search');. What we've done here is assigned a character set. Instead of searching for "a" or "bat", it's searching for anything that's a-z or 0-9 (alphanumeric).

By placing a "^" at the front of the character set, the entire class is negated - now it's looking for something other than what's in that set. Just what we need. A tip: if you want to allow underscores (for, say, usernames), change[^a-z0-9] to [^a-z0-9_]. Similarly, add a "$" to there if you want people to be able to have $ in the form field.
~~~

Next we'll be looking at the words inside the string. Again, falling back to the username example, you don't want "iamashithead" interacting with the other users. To block certain words, try this:
$validate2 = eregi('naughty|word', $information);
$validate2 = (int)$validate2;



In this example, the function returns true if it finds either 'naughty' or 'word'. Arguably one of the most fun parts of a website is this step: rattling off every cuss word you can and putting them into this list.
~~~

Suppose you're validating an address. Although you probably can only be sure about the validity of the address is by mailing something there, you can make sure it's in the right format.

When searching for a character class, you can use quantifiers to specify the quantity of what's needed. So let's say that to pass our gauntlet, an address needs to have a number in front, followed by at least four numbers.

$validate3 = eregi('[0-9] [a-z]{4,}', $information
$validate3 = (int)$validate3;



The {4,} means that it needs to find something a-z at least four times. {a} means exactly "a" times; {a,b} means at least "a" times, but no more than "b" times.

You can use quantifiers to validate based on string length, but it's easier to use $validateX = strlen($information);
~~~

Next, let's say that you need to ensure that nobody makes a username starting with "STAFF_". It'd be nice to distinguish site staff from regular users in as many ways as possible, but if I can go to your site and make "STAFF_Spearfish"; "STAFF_yourname" doesn't help at all.

So, you can stop that with an anchor, ^. This is confusing, because it's the same symbol that negates character sets.... but try to keep them straight. Just remember that when it's outside of a character class it's an anchor, like a boat --- because it's always getting thrown overboard. :pirate:

So, for this example:
$validate4 = eregi('^(STAFF_)', $information);
$validate4 = (int)$validate4;



The user is perfectly welcome to make "the_staff_is_great"; provided you haven't blocked underscores. Similarly, you can use "$" to indicate that the string being looked for must be at the end of the string to be searched.
~~~

Now, let's put this all together. Additionally, we need the string to be 3-24 characters long to comply with database restrictions.

This may look long and confusing at first, but break it down piece by piece. Ugly code can still lead to an elegant result.

For your testing pleasure, it also includes the form that's posting this information. Throw the file onto a server and have fun!

<?php
if(isset($_POST['formdata'])) {
$information = $_POST['formdata'];
$validate1 = eregi('[^a-z0-9 ]', $information);
$validate1 = (int)$validate1;
$validate2 = eregi('naughty|word', $information);
$validate2 = (int)$validate2;
$validate3 = eregi('[0-9] [a-z]{4,}', $information);
$validate3 = (int)$validate3;
$validate4 = eregi('^(STAFF_)', $information);
$validate4 = (int)$validate4;
$validate5 = strlen($information);
if ($validate1 == 0 && $validate2 == 0 && $validate3 == 1 && $validate4 == 0 && $validate5 > 2 && $validate5 < 25) {
echo "Success!  \"<i>$information</i>\" is a valid string";
// Coding goes here.... inserting to a database?  Setting cookies?  Who knows.  But it passed the gauntlet
} else { 
echo "Sorry, \"<i>$information</i>\" failed.  Here's why: <ul>";
   if ($validate1 == 1) {
echo "<li>Your string contains invalid characters.  It can only contain letters, numbers, and spaces.</li>";
} if ($validate2 == 1) {
echo "<li>Egad!  Don't talk like that! (Hotwords: 'naughty' and 'word')</li>";
} if ($validate3 == 0) {
echo "<li>That doesn't look like a valid address to me! (Must be a number, follwed by a space, then at least four letters)</li>";
} if ($validate4 == 1) {
echo "<li>Sorry, but all accounts starting with <b>STAFF_</b> have been reserved.</li>";
} if ($validate5 < 3) {
echo "<li>\"<i>$information\"</i> is too short (only $validate5 characters)!  It needs to be at least 3.</li>";
} if ($validate5 > 24) {
echo "<li>\"<i>$information</i>\" is too long (a whole $validate5 characters)!  It can't be more than 24.</li>";
}
echo "</ul>";  }
}
?>
<br />
<form action='validator.php' method='post'>
<input type='text' name='formdata' />
<input type='submit' value='Test that string!' />
</form>
<br />



Phew! Let me point out a few things:
If it passes the validation --- all of the tests turn out the way we want them to --- then it says so, and you can place code to happen. If it failed, it says so, and starts an unorganized list, and runs through the checklist of things that could have gone wrong, displaying each error as a list item in an unorganized list.
~~~

Now, let's focus on the two other things: Phone numbers and Email addresses. Phone numbers are easy using quantifiers....
$validate6 = eregi('[0-9]{3}-[0-9]{3}-[0-9]{4}', $information);



That searches for a phone number in 123-456-7890 format.

For email addresses, try this:
$validate7 = eregi('[a-z0-9'][@]{1}[a-z0-9][.][a-z.]{2,}', $information);



This isn't a sure-fire validator for email addresses, but it does stop the outrageous strings. Test yourself by trying to build an email validator that works 100% for syntax checking (for example, "ab@9.coa.awe.wer" passes this validation, while "notarealemail@a.b" fails).
~~~

I appreciate your feedback, and would love to hear about things I should have included, things that weren't explained well, or things that I got wrong (gasp!).

If this is the first time you've seen this stuff and you're still hanging on, congratulations. I was overwhelmed when I first saw it. Be sure to post below if you need more detail or more examples.

Spearfish
~~~

Pictures:
I passed validation!
Attached Image

Oh no, I failed! :crazy:
Attached Image

The finished product :^:
Attached Image

Download the validator file:
Attached File  validator.php (1.73K)
Number of downloads: 620

Download formhack.html (you aren't realy "hacking" a site --- it's just showing how easily Javascript validation can be bypassed)
Attached File  formhack.html (728bytes)
Number of downloads: 407

This post has been edited by spearfish: 18 March 2008 - 07:16 AM


Is This A Good Question/Topic? 0
  • +

Replies To: Validating forms with PHP

#2 spearfish  Icon User is offline

  • Monkey in Training
  • member icon

Reputation: 10
  • View blog
  • Posts: 746
  • Joined: 10-March 08

Posted 25 March 2008 - 07:35 PM

I'd just like to point out something interesting that came up (and couldn't find the edit button :stupid:). Let's say you need to find two numbers in the password, to be sure it's secure. You'd do something like this:

$passval1 = eregi("[0-9].*[0-9]", $pass);



The period means that anything can take that place. The star is a fancy way of saying {0,}

You also might find useful:
? = {0,1}; meaning zero or one times
+ = {1,}; meaning at least once
Was This Post Helpful? 0
  • +
  • -

#3 chrisman  Icon User is offline

  • New D.I.C Head
  • member icon

Reputation: 1
  • View blog
  • Posts: 46
  • Joined: 22-March 08

Posted 25 March 2008 - 08:07 PM

Hehe. Thanks for the appending.

BTW: <ul> starts and unORDERED list, not an unORGANIZED one. Picky, picky me. <_<
Was This Post Helpful? 0
  • +
  • -

#4 spearfish  Icon User is offline

  • Monkey in Training
  • member icon

Reputation: 10
  • View blog
  • Posts: 746
  • Joined: 10-March 08

Posted 26 March 2008 - 10:40 AM

Fine, be like that. You're right though - I looked it up.

I'm excited, this page just got indexed by Google - that's why there's so many views all of the sudden.

This post has been edited by spearfish: 26 March 2008 - 01:19 PM

Was This Post Helpful? 0
  • +
  • -

#5 Chopster  Icon User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 134
  • Joined: 29-March 08

Posted 19 July 2008 - 07:05 AM

Great tutorial man, i have been struggling with this for a while, but now it's alot clearer, applying to my project now

thanks again :^: :^:

Edit: Got it working fine, few little niggles converting it to my project, but its all good now, cheers again!

This post has been edited by Chopster: 19 July 2008 - 07:56 AM

Was This Post Helpful? 0
  • +
  • -

Page 1 of 1