Forum Moderators: coopster

Message Too Old, No Replies

Form Submission Error Handling

form,error handling,best practices

         

pmmenneg

10:56 pm on Oct 15, 2009 (gmt 0)

10+ Year Member



Hi all. Have a generic PHP page that submits form data via POST to a PHP script which then verifies and scrubs the data, and based on whether the passed data is valid or not, either commits the data to the db or not.

So, I've been doing this type of thing for years, but am just trying to find out how others handle errors/success with form submission, in terms of how you notify the user.

I AM SURE I AM DOING THIS IN A VERY INCORRECT FASHION, so after you've finished shaking your head, a little help would be appreciated :-)

In my typical case, the form-handling script gets sent POST data, and if the user entered incorrect data, they have to go back to the form and correct it. i alert them of this by sending the user back from the form handling script via Location().

Example

/form.php submits to /script/handle_form.php via POST
/script/handle_form.php check data, and if error, sends user out via
Location(/form.php?error=2);

/form.php then displays the form and an informative error message via based on the passed GET variable.

I'm sure this is incorrect, but it's always worked for my needs. Obvious problem: as the user can see the GET variable on error, they could sit there and change the value and the page would display, in theory, all of the error messages that the page is designed to spit out.

So, any suggestions?

Thanks,

paul

willybfriendly

12:39 am on Oct 16, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



First I do error checking client side via JS, including fixing obvious errors (i.e. formatting dates, telephone numbers, truncating text fields, etc.) and rejecting invalid input.

Forms are handled in a single script using functions for error checking, processing, etc. As far as the user is concerned they never leave the page until the form is filled out correctly.

I use a hidden field (e.g. "ds") to trigger the various functions.

if($ds="")
displayForm();
else if($ds="1")
checkForm();
Etc.

If the form data doesn't check out then I simply re-display it with the bad data fields highlighted (and an error statement) while the good data is preloaded (to save the user from re-entering it).

Always check for expected data rather than screening out suspect data. If it is a numeric field, confirm digits have been entered, if a phone number, confirm it looks like a phone number, etc.

pmmenneg

4:35 am on Oct 16, 2009 (gmt 0)

10+ Year Member



Thanks Willy.

I'm already checking the content with JS, so I'll just modify the script to submit the data to itself. Question for you:

It looks like you are using formulas to display/check the form, correct? So say hypothetically checkForm() fails on a few pieces of data, how are you tracking which pieces fail for when you later call the displayForm function again? Trying to get my head around the logic... i.e.

if($ds="")
displayForm();
else if($ds="1")
if(!checkForm())
displayForm();

Thanks,

Paul

willybfriendly

5:22 am on Oct 16, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



So say hypothetically checkForm() fails on a few pieces of data, how are you tracking which pieces fail for when you later call the displayForm function again?

Loop through all the variables. Flag the bad ones.

checkForm()
{
if(!phoneCheck($_POST[phone]))
$errmsg="Not a valid phone number";
if(!zipCheck($_POST[zip]))
$errmsg .= "Not a valid zip";
...
if(isset $errmsg)
return errmsg;
}

You come out of the function with an error message to post, or well formed data. If there is an error, the form is generated again, but with an error message and prefilled input areas (using existing post data) ready for the user to make changes.

If there are no errors, the data is proven clean and can be dealt with as needed - to the database, mail, etc.

Breaking the error checks off into separate functions makes the code more portable.

It is not too hard to highlight input areas or other things to draw the user's attention to the exact errors that need attention.

rocknbil

6:19 pm on Oct 17, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



In my typical case, the form-handling script gets sent POST data, and if the user entered incorrect data, they have to go back to the form and correct it. i alert them of this by sending the user back from the form handling script via Location().

Yuk! :-) You're correct, this is not user friendly at all.

Javascript is good, it saves the user time (read: enhances their experience) but keep your server side stuff in place, you know the story.

I see this a lot in PHP, separate files and a lot of header("location...") when it should all be in one script.

Here is how I handle it, it may not be "perfect" but allows maximum flexibility in modifying responses and makes it usable as well. That is, as long as they actually read your big red error messages. :-)

- Your submit form should be generated directly from your script. You can do this using a template file that you open and substitute out variable values for form values, or generate the form directly from within the script. The second is easier, but it makes your script bigger. So instead of contact.html, you have a direct link to contact.php. The overall logic at the top of your script:


if (isset([some-input-variable]) { process_form(); }
else {
$pagetitle = 'Contact Us';
$content = output_form();
output_page($pagetitle,$content);
}

For all output, you have a function, say, output_page($title,$content); This function opens your site template/skin, and places content in it, headings, etc. Do that however you like, but compartmentalize this process. You will use it often.

Function output_form() is function that . . . . duh . . . outputs the form, but the advantage is if input variables are present, you can populate them. It can also be repurposed for say, an edit form where the user edits their info. We'll use this function later in the event of errors.

When you go to process the form, you do something like this.


function process_form () {
$errors='';
$errors = check_data();
if ($errors != '') { form_error($errors); }
// no need for an else, form_errors calls output_page
// which should exit.
// add to database, email, whatever
success_response();
}

I like setting $errors to a blank string, you can test against NULL instead.

In check_data, you build an unordered list.


function check_data() {
$input_errors='';
// You'll also cleanse the data here.
// Now you go through the various inputs, depending
// on the error you may have to build different strings.
// Blank values are easy, but you may want to
// make this array a GLOBAL so you can put the array
// at the top of the script, or as configuration
// variables pulled from a database. I know PHP coders
// detest globals, but in a small script, it works.
$requireds = Array(
'fname' => 'First Name',
'lname' => 'Last Name',
'email' => 'Email Address'
);
foreach ($requireds as $key=>$value) {
if ((! isset($_POST[$key])) or ($_POST[$key]=='')) {
$input_errors .= '<li>The ' . $value . ' field is required.</li>';
}
}
// You probably want a special one to validate the
// email, and you'll probably have other special
// checks to do as well.
$input_errors .= check_valid_email($_POST['email']);
return $input_errors;
}

So function form_errors does this

(top of script)
$errtitle = 'Error Submitting Form';


function form_errors ($errors) {
global $errtitle;
$form = '<p class="red-bold">Your form could not
be submitted and contained the following errors:</p>
<ul>' . $errors . '</ul>
<p>Please make the necessary corrections and try again.</p>';
// output the form again, with all input values intact
$form .= output_form();
output_page($errtitle,$form);
}

success_response() outputs a successful title and should be a neatly formatted and printable "receipt" of the input data - of course, anonymizing any sensitive data to *****. It also will use the output_page() function.

And there you have it, all in one script, returns to form with previous input data intact, and manages the success page.

You'll wrangle a bit with populating radio buttons, select lists, checkboxes, highlighting errant fields when it errors, but that is fairly trivial to figure out.

pmmenneg

7:49 pm on Oct 19, 2009 (gmt 0)

10+ Year Member



This is really really great stuff rocknbil, have implemented this flavor of form verification, all is working perfectly.

Thanks!