PDA

View Full Version : Error Handling


Shalazar
02-22-2000, 12:53 AM
I'm creating a simple form to allow user input to be written into a database:


<?php

$db = &quot;xmy_domain&quot;;

$SQL= @mysql_connect (&quot;localhost&quot;, &quot;login&quot;, &quot;password&quot;);

if (!$SQL) {print (&quot;We're sorry, but the database is currently down. Please try again later.&quot;);
[nbsp][nbsp][nbsp][nbsp] }
else {

mysql_select_db ($db);

$result = mysql_query (&quot;INSERT INTO table_name VALUES ('$var1', '$var2', '$var3', '$var4', NULL)&quot;);

if(!$result)
[nbsp][nbsp][nbsp][nbsp] {
print (&quot;Insertion of your information into the database was unsuccessful for the following reason(s): &quot;, mysql_error());

exit;
[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp]}

else[nbsp][nbsp][nbsp][nbsp] {
[nbsp][nbsp] #go on to print information added
[nbsp][nbsp] #display rest of the page

}
?>


It works fine with my tests, but from the previous thread where Justin mentioned the lengths he goes to in error handling, I'm wondering if I could get some advice on any additional error handling mechanisms I could add to this script.

Particularly, I'm wondering if there is any information on validating each of the insertions (something like names, emails, etc.), since it seems commonplace to insert all form variables at once.[nbsp][nbsp]Is it best to validate each entry individually before inserting it?[nbsp][nbsp]Something like:

#validate entry1
mysql_query = (&quot;INSERT INTO table_name VALUES ('$entry1')&quot;);

#validate entry2
mysql_query = (&quot;INSERT INTO table_name VALUES ('$entry2')&quot;);

.
.
. (and so on)

Or is it more appropriate to place all your validation code before executing your mysql_query = (&quot;INSERT INTO table_name VALUES ('$foo', '$bar')&quot;); statement?
[nbsp][nbsp] In this second scenario, that would allow sequential validation of each variable in a series of regulartory expressions, allowing exit if any given variable failed the test, or progression all the way through if each one succeeded - resulting in insertion of them all, which seems to be the correct method to my limited experience.

I'd appreciate everybody's advice.[nbsp][nbsp]I'm enjoying playing with this stuff more and more everyday :)
[This message has been edited by Shalazar (edited 02-21-00@11:57 pm)]

Justin
02-22-2000, 12:31 PM
The more forms you write (and the more user input you think you can trust), the better you will get at validating input. For starters, validate all fields first, then do the work. Also make sure to escape single quotes before inserting - otherwise if $var = &quot;justin's input&quot;, MySQL will error on that:
</font><font face="Courier" size="3">
$var = addslashes ($var);
</font><font face="Verdana, Arial" size="2">
Or:
</font><font face="Courier" size="3">
$var = ereg_replace (&quot;'&quot;, &quot;''&quot;, $var);
</font><font face="Verdana, Arial" size="2">
I usually have a function near the top of my scripts:
</font><font face="Courier" size="3">
function fix ($text) {
[nbsp][nbsp] $text = ereg_replace (&quot;'&quot;, &quot;''&quot;, $text);
[nbsp][nbsp] return ($text);
}
</font><font face="Verdana, Arial" size="2">
Then I just say:
</font><font face="Courier" size="3">
$var = fix ($var);
</font><font face="Verdana, Arial" size="2">
You will want to validate the length of the input, what characters are/aren't allowed, and so on - never assume, for example, because you use a one line text box that the user can't find a way to put a line feed in the input... Also never assume that the user can't edit the &quot;hidden&quot; form fields, so always re-validate when using a multi-page form.

I've learned the hard way - seems the more validation you add, the more ways people will find to break the validation. Get too lax and they'll enter in all sorts of stuff. Get too strict and you'll find that there are legitimate entries you didn't think of (international phone numbers, for example - or ZIP codes - or Compuserve email addresses which contain commas - and so on).

Hope this helps get you started in the right direction :)

------------------
Justin Nelson
FutureQuest (http://www.FutureQuest.net/index.php) Support
[This message has been edited by Justin (edited 02-22-00@11:32 am)]

Shalazar
02-24-2000, 11:33 PM
Looking at what needs to be done, in the validation of several sets of user input, I felt the following algorithm may be the first step to a correct validation script:

if (!validation_step_1){
[nbsp][nbsp] echo &quot;Sorry, $var1 is invalid, please try again&quot;;}

[nbsp][nbsp] else {
[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp]if (!validation_step_2){
[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp] echo &quot;Sorry, $var2 is invalid, please try[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp]again&quot;;}

[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp] else {

[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp] #connect to database and INSERT variables
[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp] }

Using an if clause where the pattern match fails would be much better for nesting.[nbsp][nbsp]If it fails validation, then you can give an error within the if statement, saving the else to nest the next if statement for the subsequent variable. This would allow sequential validation of each variable, ensuring connection and insertion into the database would occur only if each variable were correct.

Am I on the right track of thinking here?
------------------
Shalazar

www.charisma-carpenter.com (http://www.charisma-carpenter.com)
The Internet's Premier site for everything Charisma.

Justin
02-25-2000, 12:05 AM
That would work - what I usually do first is define an error() function:

function error($msg) {
[nbsp][nbsp] print &quot;<h3>Oops!</h3>
[nbsp][nbsp] An error has occurred:
[nbsp][nbsp] <ul> $msg</li>[/list]
[nbsp][nbsp] Please use your <a href=\&quot;javascript:history.back()\&quot;>Back</a> button
[nbsp][nbsp] and correct the above errors.&quot;;

[nbsp][nbsp] include &quot;footer.php&quot;;
[nbsp][nbsp] exit;

}

Then I do this:

if (!eregi (&quot;^[a-z0-9]{2,26}$&quot;, $firstname)) error (&quot;First Name is invalid.&quot;);
if (!eregi (&quot;^[a-z0-9]{2,26}$&quot;, $lastname)) error (&quot;Last Name is invalid.&quot;);

And so on - no need to nest the if's, as that would eventually get really messy (imagine a long order form, with multiple steps ;)[nbsp][nbsp])[nbsp][nbsp]This way, as soon as one of the conditions fails, it errors out and exits the script.

Another way I do it sometimes:

if (!eregi (&quot;^[a-z0-9]{2,26}$&quot;, $firstname)) $error .= &quot; First Name</li>&quot;;
if (!eregi (&quot;^[a-z0-9]{2,26}$&quot;, $lastname)) $error .= &quot; Last Name</li>&quot;;

# more lines like this...

if ($error) {
[nbsp][nbsp] print &quot;<h3>Oops!</h3>
[nbsp][nbsp] The following fields are invalid:
[nbsp][nbsp] <ul>$error[/list]
[nbsp][nbsp] Etc etc - go fix it.&quot;;

[nbsp][nbsp] exit;

}

As you can see there are many ways to do error control - which is right depends on the situation, target users, and of course programmer preference. I stay away from the nesting if's mainly because I would lose count of my {braces} and tabs etc... you'd end up with code far to the right if you had a lot of fields to validate (and if you indent your code :))

Hope this helps.

------------------
Justin Nelson
FutureQuest (http://www.FutureQuest.net/index.php) Support
[This message has been edited by Justin (edited 02-24-00@11:07 pm)]

Shalazar
02-25-2000, 01:12 AM
Thanks for the advice on that Justin.[nbsp][nbsp]You're error() function is a delightful idea, and maintains the message and exit options in one single place.

Now on to learning more about regular expressions hehehe

Shalazar
02-25-2000, 07:39 PM
I'm currently working on crafting the correct regular expressions to handle my form input.[nbsp][nbsp]I'm finding this rather interesting at the range of things you can look for patterns in.

Anyway, $first_name and $last_name are varchar(25), of the form of:

if (!eregi (&quot;^[a-z0-9]{2,25}$&quot;, $first_name)) #error

Then I have an e-mail check, varchar 35 chars long, that must be viewed at http://www.charisma-carpenter.com/test/ otherwise it screws up UBB.

I've tweaked this as best I can, and think it can handle all natural e-mail variations.[nbsp][nbsp]Must start with at least one alphanumeric character/underscore/hyphen, followed by zero or more occurences of a period OR comma (thanks for the compuserve tip Justin!) followed by alphanumeric stuff.[nbsp][nbsp]Then the @ sign.[nbsp][nbsp]Then at least one instance of an alphanumeric character, followed by one or more instances of a period and more alphanumeric characters (allowing foreign addresses like hotmail.co.uk)

Now, I understand how to define the length of the string for something like the name, but is there anyway to use the {num1,num2} limit on the email check?[nbsp][nbsp]Or should I just stick with my maxlength=30 tag hardcoded into the form element?

The rest of my elements are listed as text elements, mainly comment or suggestion blocks for the user.[nbsp][nbsp]I know no HTML will be echoed back to the user, but still would like to prevent HTML tags, javascript, SSIs, etc. from being included in the text blocks.[nbsp][nbsp]Is this process very involved?[nbsp][nbsp]Or am I looking at something as simple as addslashes() or magicquotes?

Something like:


function validate_text($text) {
[nbsp][nbsp][nbsp][nbsp]addslashed($text);
[nbsp][nbsp][nbsp][nbsp]return $text; }


Assuming that's correct.[nbsp][nbsp]Is that considered validation of a text block?[nbsp][nbsp]Or does it require something like:

if ($text_block_1) {
[nbsp][nbsp] validate_text($text_block_1);
[nbsp][nbsp] }
[nbsp][nbsp] else { #error }
[This message has been edited by Shalazar (edited 02-25-00@6:50 pm)]

Shalazar
02-25-2000, 08:23 PM
And this may be a ludicrous question, but how does one validate something like checkboxes or radio buttons? Just check to see if they were successfully filled out, else error?