Catch-all PHP Form Processor

Introduction

Through my work in web development I’ve noticed the high number of times I need to write out a contact or registration form for a client. Each time I get the form fields together and then decide how I want to process the form. This usually entails a client-side validation of certain fields (required fields, email validation, etc) and then a back-end check of those fields before processing them. This process can get pretty repetitive if you do a high volume of projects or sites needing this function. I was looking for a way to process any form I create with the same script each time and thus produced this php script. It’s a lightweight, single file form processor that has a number of options. The goal of this script is to provide asingle file resource available to use over and over. For certain forms you may want to implement your own client-side validation of fields before sending them to the form processor. Let’s explore the features:

Features

  • A single php file inspects form data and displays it to the user for review. Upon review the user can print and/or submit the results once all fields are valid (as discussed below)
  • Can submit results to 1 or more email accounts
  • Can send a blind carbon copy (bcc) as well
  • Email results can be plain text or HTML formatted
  • Script can be used in a standalone environment or as a part of your existing site template
  • You can define which fields are required
  • You can define which fields (if any) should not be displayed back to the user when they check the results before submission
  • Checks for validity of email address (to confirm it is, in fact, an email address)

Requirements

This script requires PHP 4.0.7 or newer. ‘Installation’ is as simple as putting it on your server wherever you need it. I pre all of my forms by hand but you can use any WYSIWYG editor to draw up a form and give it the appropriate fields and form method and action.

Form Field Compatibility

This script successfully processes the following field types:

  • text
  • radio
  • checkbox
  • select & options(single and multiple)
  • hidden
  • textarea
  • image

Passwords have not been tested as they are not typically something that’s processed and emailed as a result. Be sure to read below to understand how to successfully setup multiple checkboxes within a single “name” and multiple select options within a single “name”.

Setup & Customization - The Form

The Basics

Catch-All Form Processor is nothing but a processor. The form pre must be provided on your end. This script does a few things that require you to put a little bit of thought into your form. For every input field you have you must give it a name (a standard in XHTML). How you name said fields will determine how they are displayed in the results. I have followed the standard of “pretty links” all around the web now. If you have a field such as “First Name” you would (probably) want to name it “first-name” or “first_name”. This is processed in the script to read “First Name”. For example:

<input type="text" name="first-name" id="first-name" value="Erik Reagan" />

This will be read by the script as the field “First Name” having a value of “Erik Reagan”

<textarea name="additional-comments">Text area  here</textarea>

This will be read by the script as the field “Additional Comments” having it’s relative value

Form Submission

This is very important! In order for the script to process the form it must recognize the submit button. Your submit button must have the name set to ’submit’ to work. Image submit buttons are also acceptable as long as you give them a value of ’submit’ AND give them a name.

<input type="submit" name="submit" id="submit" value="Submit Results" />
The above is acceptable
<input type="submit" name="submit" id="formbutton" value="Blast Off!!!" />
The above is acceptable
<input type="image" src="button.jpg" id="formbutton" name="formbutton" ↵
    value="submit" alt="Blast Off!!!" />
The above is acceptable
<input type="image" src="button.jpg" id="formbutton" value="submit" ↵
    alt="Blast Off!!!" />
The above is NOT acceptable (name="something" is missing)

Require Fields

If you have fields you need to require (such as name, email, etc) you can simple append “required” to the FRONT of the name. For example:

<input type="text" name="required-first-name" id="first-name" value="Erik Reagan" />

This will alert the user if they have left a required field blank. I would suggest showing the user that the field is required by marking it somehow in your form Requiring a <select> input is a bit different. To do this you’ll need to adjust the name from something like “cars[]” to “required-cars[]” and then add an option similar to this:

<option value ="didnotchoose" selected>Choose One</option>

You can put anything you want in the “Choose One” area. This will require the select to be used. You can read more about the select usage below.

Ignore Fields

Many times developers use hidden input values during form submission. Another common factor (mostly seen in registration forms) is a terms and conditions text area. When filling out forms of this nature you typically do not want the user to ‘review’ this information. To hide these fields from the users review you can simply add “ignore” to the FRONT of the name. For example:

<textarea name="ignore-terms-and-conditions" rows="8" cols="40">
Terms and conditions that go on and on and on and on....
</textarea>
The script breaks down this name as "Terms and Conditions" and does not display
it to the user. Ignored fields are, however, included in the emailed results.

Email Validity

Any field with the string ‘email’ in it will be flagged as needing to be a valid email address. The standard regular expression is used to check for this validity. For example:

<input type="text" name="email-address" value="erik@erikreagan.com" id="email" />
The script will flag this field as needing to validate as an email address because it
sees 'email' in the name. It will display as "Email Address"

<input type="text" name="user-e-mail" value="erik@erikreagan.com" id="useremail" />
The script will flag this field as needing to validate as an email address because it
sees 'email' in the name. It will display as "User Email" because the hyphen is
treated like every other hyphen and is replaced by a space

<input type="text" name="users-mail" value="erik@erikreagan.com" id="usersmail" />
The script will <strong>not</strong> flag this field as needing to validate as an
email address because there is no full string of 'email' in the name

Form Method & Action

In order for this script to work without tweaking the core of the php the method of the form must be POST. For example:

<form method="post" action="path/to/process-form.php">

Notice the action in the above example. This is what you should set the action to (but fill in your path) if you are using the form processor as a standalone script. If you are using it inside your own site this may vary. You could leave it blank (action=”") if the script is already loaded into the same page. I trust if you are including the script in your own template you can tweak the settings as needed.

Setting up Checkboxes and Selects for multiple options

Many times you will need to allow the user to check multiple boxes or select multiple options. In order to process the results as one result you must tell the form and script that the results are lumped into an array. This is a simple process but if overlooked the results will not be pleasing

<p>Favorite Types of Cars</p>
<select name="car[]” id=”car” multiple>
  <option value =”Volvo”>Volvo</option>
  <option value =”Saab”>Saab</option>
  <option value =”Opel”>Opel</option>
  <option value =”Audi”>Audi</option>
</select>

In this example the Select name is “car[]“. The brackets are saying to the form “Put the following results into an array” and then when the results are being processed the script sees the array and displays the results as 1. For example if the user were to pick Volvo and Audi from the above example it would be displayed as “Volvo, Audi”. You can achieve a similar result by using check boxes

Volvo <input type="checkbox" id="volvo" name="car[]” value=”volvo” />
Saab <input type=”checkbox” id=”saab” name=”car[]” value=”saab” />
Opel <input type=”checkbox” id=”opel” name=”car[]” value=”opel” />
Audi <input type=”checkbox” id=”audi” name=”car[]” value=”audi” />

Setup & Customization - The Script

I have placed the primary settings at the top of the process-form.php file. These variables should be modified to your preference. I do not guarantee support of any modification of the actual script! Let’s take a look at each option. The default values are displayed below.

  • $usingTemplate = false; This variable defines whether or not you are using the script by itself or within your design or site. The available options are simply ‘true’ or ‘false’
  • $customForm = “path/to-your/form.php”; This variable is commented out by default. If you set $usingTemplate to ‘true’ then you can include your form within the process-form.php script by putting the path to your form here. The form.php file should contain only the form elements. There is no need for doctype, headers, etc because this (by default) includes your form within the script. This is not recommended because you would need to tweak the process-form.php file for design or style changes but I made it an option for those who are interested.
  • $emailRecipient = “recipient@theirmail.com”; This is fairly obvious. One note, however, is acceptable formats. You could use the above format (handle@domain.com) or you can use a format such as “Erik Reagan <erik@erikreagan.com>”. You can also string together multiple recipients by adding a comma between. Two examples:
    $emailRecipient = "erik@erikreagan.com, erik@idealdesignfirm.com";
    or
    $emailRecipient = "Erik Reagan <erik@erikreagan.com>, Big Dorky Guy ↵
        <erik@idealdesignfirm.com>"
  • $bccRecipient = “another-email@domainname.com”; This is for sending a blind carbon copy (bcc) to additional addresses
  • $forwardUser = true; By default the script shows the user a success page and then using javascript to forward to a new location. If you do not want to forward the user for any reason set this value to ‘false’.
  • $finalDestination = “http://mywebsite.com/thankyou.html”; If $forwardUser is set to ‘true’ then this is the location you will forward them to. It can be as specific as above or it can be relative to your site. For example if you just want them to go to your homepage (assuming your homepage is somethinghere.com) you can set this value to “/”.
  • $subject = ‘My PHP Form’; This is the subject of the email sent containing the results
  • $subjectIsInForm = false; This is used if you are allowing the user to type in the subject
  • $subjectField = “required-subject”; This is used to tell the script what the input field name is of the subject if the user is typing it in manually.
  • $fromName = “Your Name”; This is the “From” Name when when sent.
  • $fromNameIsInForm = true; This is the same function as $subjectIsInForm respective to the from name.
  • $fromNameField = “required-your-name”; This is the same function as $subjectField respective to the from name field.
  • $fromEmail = “handle@domainname.com”; This is the “From Email” address when sent.
  • $fromEmailIsInForm = true; This is the same function as $fromNameIsInField and $subjectIsInField respective to the from email field.
  • $fromEmailField = “required-your-email”; This is the same function as $fromNameField and $subjectField respective to the from email field.
  • $includeTimestamp = true; If set to true this adds the date and time at the end of the form results once emailed.
  • $includeBlankFields = true; If set to true this includes fields that the user did not fill in and they are given a value of “[ left blank ]“.
  • $emailHTML = true; This allows you to define what type of email formatting is sent. Set this to false if you prefer plain text. A vast majority of email clients support the level of HTML that this script produces so I suggest leaving it where it is unless you really need plain text emails sent.
  • $headerTroubles = false; This variable corrects an error some Unix servers have when processing email headers defined by PHP. If you are having issues with email headers try setting this to ‘true’ and submit the form again.

Custom Style Sheet

If you choose to include this within your own template or design I’ve listed below the fields you may want to customize in your stylesheet(s). There are three portions to the display of the processed form. The main DIVS are ‘top’, ‘results’ and ‘email’. ‘top’ contains the header only (”Form Results” & “Please Review Your Information”) ‘results’ contains - you guessed it! - the results of the processed form. Keep in mind thiscould include error results. They are inside a DIV of their own nested inside of the ‘results’ div. ‘email’ contains the hidden fields while the user reviews their information. Also of note is that the Print, Email and Back buttons are inside this div. Here’s the general layout (including just about every option):

  • #top
  • #top > h2
  • #top > h5
  • #top > h5.red
  • #results
  • #results > div.error
  • #results > div.error p
  • #results > div.error strong
  • #results > div.error ul
  • #results > div.error ul li
  • #results > div.error p a
  • #results > ul#display
  • #results > ul#display li
  • #results > ul#display li strong
  • #results > ul#display li span
  • #email
  • #email > input#print
  • #email > input#submit
  • #email > input#back

PHP Functions Used in script

  • array_key_exists()
  • count()
  • date()
  • define()
  • empty()
  • ereg()
  • htmlspecialchars()
  • implode()
  • in_array()
  • is_array()
  • mail()
  • preg_replace()
  • stripslashes()
  • strstr()
  • strtolower()
  • str_replace()
  • ucwords()

Future Features?

  • Possibly allow choice of including ignored fields in email or not
  • Possibly allowing specification of which fields don’t go in email
Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • bodytext
  • del.icio.us
  • Facebook
  • Mixx
  • Google
  • eKudos
  • Live
  • Reddit
  • Spurl
  • StumbleUpon
  • Technorati

If you enjoyed this post, please consider to leave a comment or subscribe to the feed and get future articles delivered to your feed reader.

Comments

so, your first name is erik reagan?

Correct. My last name, naturally, is “Rocks”

You do the math :)

(I’m just glad someone read through and caught that)
:)

I was wondering if you could comment on a few things i noticed when using your form processor.

1. When the mail is delivered, the sender is listed as “(unknown sender)” in my gmail inbox.

2. The html formatting doesn’t appear to work correctly, as it diplays the formatting tags rather than displaying the actual formatted message.

Nick
I uploaded the process-form.php file to 4 different servers and used the sample-form.html example. In the process-form.php file I set the to field to my gmail account and it worked just fine for me. Have you adjusted any of the php functions beyond the variables at the top of the script?

You can take a look at my results here

Hey Erik
I put your exact forms processor code on my server, and modified the header as follows:

$usingTemplate = false;
//$customForm = “path/to-your/form.php”;
$emailRecipient = “nicholas.romanowski@gmail.com”;
$forwardUser = true;
$finalDestination = “/”;
$subject = ‘My PHP Form’;
$fromName = “Nick Romanowski”;
$fromEmail = “nicholas.romanowski@gmail.com”;
$emailHTML = true;

You can see the results from my gmail inbox at:
http://www.paweblabs.com/php_form.jpg

You can see the live example here:
http://www.paweblabs.com/sample-form.html

Thanks a lot for your time.

thanks alot for all that info
regards
sam

Blind CC might be nice.
Excellent PHP BTW

@nick
I’m glad we had the opportunity to chat about the script on AIM. I’m looking forward to hearing about your results

@sam
It’s my pleasure to share!

@christo
Good thought. I’ll plan to add that as a main variable in the next round. Thanks :)

Also, another option might be to allow the submission to bypass the preview page and go straight to a success page. The preview, for some, just gives the them another opportunity to second guess themselves or accidentally close the browser not knowing they have to send the results.(my 2 cents)

I’ve been looking for something like this for a while. I haven’t set it up yet, but will re-post when I do.

One question with respect to emails - would it be possible to toss a simple email munger into the script so that

$emailRecipient = “recipient@theirmail.com”;

becomes something like (this is a takeoff from a munging javascript I use on my site). I don’t know enough to know whether it even makes sense in php):

$ename=”recipient”;
$etag=”@”;
$ehost=”theirmail”;
$etld=”.com”;
$emailRecipient = $ename.$etag.$ehost.$etld;

Does this make any sense?

Mark

Yes this is possible but I don’t understand it’s use. What purpose would you have in breaking it up and having PHP put it all together later? Since the recipient is a variable you are defining when you setup the script it’s almost the same thing as the following:

$subjectFirst = “My”;
$subjectSecond = ” PHP”;
$subjectThird = ” Form”;
$subject = $subjectFirst.$subjectSecond.$subjectThird;

This is just extraneous code that turns a 1 line variable into a 4 line variable (or 5 in the case of your example).

Perhaps I’m reading it wrong and you are aiming at a different purpose. Please do correct me if I am wrong.

Erik,

The idea of munging email is to avoid bots that will read the php code, recognize an email string and use it for spamming purposes. The theory is that by breaking it up into code variables, and then putting the variables together, the bots don’t see it as an email address and won’t harvest it.

Maybe this is no longer an issue (the bots don’t read php or the bots are smarter so it won’t help) but the javascript version was recommended to me years ago to allow me to post my email address on my web site without getting spammed to death.

To my knowledge bots cannot read any of the php code that is processed because it’s all done on the server end before it’s displayed in the browser. In the case of the recipient email address it is never displayed in the browser. If this was a client side script the bot sniffing would be a concern.

Thank you. That answers my question.

Erik,

This is truly just what I have been looking for. I’m playing with it on my site at http://www.midlifeflight.com/quiz2/flight_review.htm . It is doing just what I need (and much cleaner than before). what I need, and it was very simple to set up (the form is one I have been using; just changed a couple of things to conform it to what your script is looking for).

I’ll probably mess around a bit so that the answer sheet and redirect that the visitor sees has the same “look and feel” as the rest of the site but other than that…

Thanks again. And Kudos on a fine script.

Firstly, this script is AMAZING. Many, many thanks Erik. Secondly, I notice that sometimes it takes a long time to download the results email in outlook…is this common?

I added a CAPTCHA to it… and it works weel. The comments field on my form is trimming though. Don’t know what I did wrong.

Looks like the apostrophe character will cut off the rest of the characters following it - is there a fix to this?

@Barry
I was thinking of adding CAPTCHA to one example as well. May I see yours?

@Jay
I typed a straight apostrophe into each field in my sample-form.html and could not get it to cut off the following characters. Can I see your form in action?

Hey Erik,

Finally figured out what was giving me trouble with your script and Gmail.

I stripped the “\r” from your headers and just used “\n” instead of “\r\n”. Using “\r\n” created a double rowbreak resulting in Gmail thinking headers were all sent after first row.

Another minor thing i noticed is that if you make multiple selections in the select box, one being “choose one”. The form errors out, saying the field was left blank and “didnotchoose” is displayed as one of the selections.

@Nick
That’s really odd because it works just fine in Gmail for me (as we discussed). I wonder what causes Gmail to interpret the data differently. If anyone knows please let me (us) know. All of my tests were on Apache servers and Nick’s (correct me if I’m wrong) were on Litespeed.

Thanks for noticing the ‘didnotchoose’ error upon inclusion of selection. I’ll write it in so that it’s not included if someone chooses that among other options.

I just wanted to update and let everyone know updated version is in the works with many of your suggestions taken into consideration. It will be released in a week or two and, I believe, will add some well needed missing features and fix a few bugs that have been noted.

If you would like to know when this is released you can follow the feed on this post here.

The update is here! Version 1.5. Looking forward to comments…

I’m in the throes of testing this excellent form processor, and think you ought to know about this section of the code:

if ($subjectIsInForm) { define(’SUBJECT’, $_POST[$subjectField]); } else { define(’SUBJECT’, $subject); }
if ($fromNameIsInForm) { define(’SUBJECT’, $_POST[$fromNameField]); } else { define(’SUBJECT’, $fromName); }
if ($fromEmailIsInForm) { define(’SUBJECT’, $_POST[$fromEmailField]); } else { define(’SUBJECT’, $fromEmail); }

I’ve had to change SUBJECT in the last 2 lines to the correct names!

Also, I’m having trouble with the fromNameIsInForm and fromEmailIsInForm variables. They’ll accept “name” and “email” but turn their noses up at “required-name” and “required-email” respectively.

I would never be able to conceive and implement a processor like this. Thank you for not only doing so but also making it freely available. God bless you!

WOW! That’s what I get for copy and paste, eh! I’m so sorry for releasing the code like that and thank you very much for catching it. I have corrected it and it has been re-uploaded.

I tested the custom name and email option and it’s working fine for me. Make sure you have the field name represented in the php variable correctly. I’ve also adjusted the sample-form.html that is packaged with the script to use this aspect of the processor. Let me know if you need any more help with it.

Again - Thank you!
:)

found your site on del.icio.us today and really liked it.. i bookmarked it and will be back to check it out some more later ..

We have two forms on our Drupal site, one at http://5loaves2fishes.net/node/6 and the other at http://5loaves2fishes.net/node/119 (bottom of the page in both cases). I’ve now integrated the processor into the site and it works absolutely flawlessly - there’s seamless progression through the form submission process and return to the original page. Totally brilliant, and a real answer to prayer.

I would like to modify it, however, by changing the “print” option of the review screen to a “back” button so people have the opportunity to correct any mistakes. Our forms are very simple so printing is not an option people are likely to want. I have the code but don’t know where to put it. A hint would be great!

Once again, thank you so much for this script.

Hey Watchkeeper
If you’re using a text editor that shows the line numbers take a look at line 201. That’s where I’m adding the Print button to the display block. Since you said you had the code to use I’ll leave it at that. Let me know if you have any other questions. I’m glad you’ve found great use from the script!

Thanks, Erik. I use Notepad2 (http://www.flos-freeware.ch/notepad2.html) which not only has line numbers but auto tag completion, syntax highlighting and other bells and whistles. ;-)

In the meantime, here are two more items for your consideration:

1. In the line:
$block = “\nThere was an error processing the form.\n\n”;
the closing paragraph tag is missing its / i.e.
\n\n should be \n\n

2. When submitting text from a text area, the processor throws a fit when confronted by a single apostrophe. So a paragraph that begins “I’ve decided to blah blah blah …” appears in the e-mail as “I”. Everything after and including the apostrophe is binned.

OK, trying No, 1 again since the tag was parsed:

1. In the line:
$block = “\n{p}There was an error processing the form.{p}\n\n”;
the closing paragraph tag is missing its / i.e. {p}\n\n should be {/p}\n\n.

I’m absolutely certain you know what {p} represents!

Thanks for catching that closing paragraph tag. It has brought a bigger problem to my attention. Lines 209 and 207 are switched. I’ll update the .zip soon.

I think the problem with the apostrophe is due to magic quotes being turned on. Do you know if they are on in your PHP settings? I have not experienced this apostrophe issue in the textarea.

This looks fantastic, and what I’ve been needing for a while, but it doesn’t seem to be available for download anywhere. I may be blind, but can you point me in the right direction?

Thanks!

Haha. That’s what I get for changing themes. The download link and other info is part of the custom fields meta. Clearly that is not built in to this theme by default. I’ve made the adjustment so the download (and demo) are available at the top of the page now.

Thanks, David. Looking forward to your thoughts…

Leave a comment

(required)

(required)