A Single Article
Read it, comment, and share it with your friendsEasy form processing with PHP
I was working on a simple contact form processing script yesterday and I needed it to be really flexible, because this one script was being used to handle 8 different forms in 8 different places. AJAX was being used to prevent spam and return the response, so I didn’t need to deal with any redirects, but I still had to handle different inputs depending on which form was submitted. With inputs, as always, there is the problem of sanitizing data.
A very procedural approach would involve something like the following:
1 2 3 4 5 6 7 8 | if( isset( $_POST['name'] ) ) { $name = htmlspecialchars( stripslashes ( $_POST['name'] ) ); } else { // error, blah blah blah } |
Of course, if I decide to change the way I clean data later on, I would have to change this for every single input. So normally I would write a custom function:
1 2 3 4 5 6 7 8 9 | function sanitize($s) { return htmlspecialchars( stripslashes ( $s ) ); } if( isset( $_POST['name'] ) ) { $name = sanitize ( $_POST['name'] ); } |
This is allright, but there are a lot of things lacking:
- I still have to do
isset( $_POST[ ... ] )all the time, which is a lot of stuff to type. I don’t even want to have to check if something is set all the time, I just want to process it and check it later when I am done accepting inputs. - I don’t have anything yet for handling required/optional inputs and returning errors if something required is not entered.
- Checkboxes don’t submit anything, they are just set or not set. In their case, I just want to know what was set. My current function is useless for them.
So I thought about how to really make a simple, flexible way to handle all kinds of form input. I decided a couple things:
- There are two kinds of form inputs: optional ones, and required ones. I should have an easy way to check that all required inputs were filled. So, I could have an array for all the optional inputs, and another for all the required inputs. After I accept all the inputs, I could just run through the second array and make sure everything has a value. If anything doesn’t, that’s an error.
- There are two kinds of responses: either a list of errors, or a message saying that everything went fine. Since I mentioned that I will build an array of errors, I will then check that the array is empty. If it is, that’s success, and if it’s not, then I print out all the errors.
- Every form input except for checkboxes returns a value. For checkboxes, I should just check whether they were set or not. So I need a separate function to accept checkboxes, but this is fine since they are optional anyway. I could use an extra array to hold them too.
With these ideas in mind, I wrote this code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | /* Four arrays to store data */ $optional = array(); $required = array(); $checked = array(); $errors = array(); /* Sanitize POST input */ function sanitize($s) { /* Notice $s is the name of the input, not the value itself */ if( isset( $_POST[$s] ) ) { /* Could do any number of functions here */ return stripslashes( $_POST[$s] ); } else { /* Empty string, also defined as NULL */ return ''; } } /* Check if a checkbox was set */ function check($c) { if( isset( $_POST[$c] ) ) { /* Notice I don't want a value, I just want to keep the name */ return $c; } else { return ''; } } /* Ready to handle a form (simple example here) */ $required['name'] = sanitize('name'); $required['email'] = sanitize('email'); $optional['location'] = sanitize('location'); $optional['website'] = sanitize('website'); $checked['subscribe'] = check('subscribe'); /* Now check all required inputs */ foreach($required as $key => $value) { /* '' means empty input */ if( '' == $value ) { /* Just a list of what's missing */ $errors[] = $key; } } if( count($errors) > 0 ) { // we have errors, handle that } else { // success! send e-mail, insert to DB, etc. } |
Notice something about this code:
- The check for set and data sanitization is all wrapped in the sanitize function.
- I only have to check for missing required stuff once at the end.
- The functions are longer than the example processing itself, but these functions could be reused for any form processing on just about any form.
See, it’s really simple to use and I never have to type another $_POST[]. Plus, I could also add data validation to this without much trouble. I could give sanitize one more parameter to define some possible validation routines. Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* $v is validation routine empty means no validation (default) */ function sanitize($s, $v = '') { if( isset( $_POST[$s] ) ) { switch($v) { case 'email': // check if it's a real email break; default: return stripslashes( $_POST[$s] ); break; } } else { return ''; } } |
Anyway, you get the point; this is a really simple, clean, and reusable way of handling form input. It’s great if you want to write one script that can handle multiple forms, or even if you want a way of accepting input apart from any other processing you might do afterward. If it looks useful to you, you can use the ideas I mentioned here. And if I made a mistake, let me know. I haven’t had the chance to test this code.
Get a Trackback link
2 Trackbacks/Pingbacks
Other blogs referencing this article6 Comments
Responses to my articleI’ve not tried this myself (I’ve only just thought of it), but surely it would just be easier/more compact to build the arrays into the actual form elements.. e.g.
input name="required[name]"..and then just loop through the required array and check for empties?
foreach ($_POST['required'] as $key => $value) {if (empty($value))
// do your error handling here
}
You can then deal with any non required elements and sanitisation afterwards. That seems more efficient than having all those arrays etc. Would need to test it to be sure, of course.
(I’ve no idea how well the code in this will come out, I can’t remember what WordPress strips!)
Jem, I’ve never known that you can put an array right into a form element. Are you sure about this? Seems like I would have seen it before if it were possible.
Also, in some cases you aren’t the one who wrote the original form and you can’t change it, or at least you can’t rely on every form to have “required[name]” and “optional[name]” in an environment where a lot of people are involved and not every page is yours, so I’d say the code I showed is a bit more flexible for that.
I’m surprised you’ve not come across using arrays in the HTML forms before - it’s how you gather data from things like multiple-option checkboxes and radio buttons effectively. I’m sure there are lots of resources on it but this was the first I found in google: http://tinyurl.com/2seqt6
Obviously if you can’t change the form it’s not going to work, but otherwise I see no reason why it wouldn’t
Oh wow Jem, I had NEVER heard of that before. That’s great stuff. Like I said, it’s not too useful for my current situation when I’m dealing with a lot of forms in a lot of places and I can’t necessarily change the markup, but I will definitely use that in situations where I have complete control.
Jem, yes but that would be easy to bypass for someone wanting to cause havok.
name=”required[name]”
could be erased using a simple firefox extension that allows me real time editting of the html. It’s easier to declare required fields on the backend, where users can’t edit them.
Kylee, I think that could lead to security issues for the site. It could be used to overwrite another Array just by rewriting the HTML form, don’t you think?
ps. great article!
Leave a comment
Share your thoughts with the worldYou can use Markdown, or you can use these tags:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>Please keep comments respectful and on topic.
This form is guarded by Akismet, so don't waste your time trying to submit spam. It won't work. Ever.