Skip to page content or skip to Accesskey List.
Search evolt.org
evolt.org login: or register

Work

Main Page Content

Clever forms with PHP

Rated 3.7 (Ratings: 7) (Add your rating)

Log in to add a comment
(20 comments so far)

Want more?

 
Picture of codepo8

Chris Heilmann

Member info | Full bio

User since: July 29, 2002

Last login: April 27, 2006

Articles written: 17

The form problem

Forms have always been a nuisance in Web Development. They need HTML and backend code, render differently on each browser and stubbornly refuse to use styles consistently on browsers. Furthermore their elements send different data and need to be initialised differently depending on what they are.

When checking a form for mandatory entries, you often have to re-display the form with the previously entered data, and a highlighted version of the missing form elements. This is hard work, which is why a lot of lazier developers use a Javascript "back" button instead of a scripting solution that highlights the missing mandatory elements.

Repopulating forms with PHP

In PHP it is rather easy to repopulate a textual form element:

<input type="text"
  id="Name" name="Name"
  value="<?PHP echo $_POST['Name']==''?'':$_POST['Name'];?>" />

It is trickier with checkboxes:

<input type="checkbox"
  id="Name" name="Name"
  value="<?PHP echo $_POST['Name']=='on'?'':'checked="checked"';?>" />

Radio buttons and select boxes need a check for each of their options or some Javascript to highlight them. In any case, it is a drag.

Bobby watches you

This whole dilemma increases when you need to adhere to accessibility standards. Although not really an accessibility problem, online tools such as Bobby moan about form elements that don't have an initial value. To avoid this, designers add a dummy value, that has to be stripped again from the data once the form is submitted.

The wishlist

You want a function that displays a form element. The element should get a meaningful initial value that does not get submitted in the end.

As an extra for Javascript-enabled browsers, text elements should get emptied when you click on them if they contain the initial value.

If the element is a mandatory field and is empty, or contains the initial value, it should get highlighted. If the form has to be re-displayed due to some other element missing, the element should display the last submitted value.

The function should do that for text boxes, text areas, checkboxes, radio buttons, and select boxes. Also, it should not change any additional elements and attributes like accesskey, taborder, classes or colgroups.

Function 1: Displaying, initialising and highlighting the form

function add($f){
  global $errorindicator,$errorclass,$Javascript;
  $tocheck=explode(',',','.$_POST['required']);
  preg_match('/id="(.*?)"/i',$f,$i);
  preg_match('/name="(.*?)"/i',$f,$n);
  preg_match('/type="(.*?)"/i',$f,$t);
  preg_match('/value="(.*?)"/i',$f,$iv);
  $n=$n[1];$iv=$iv[1];$i=str_replace('_',' ',$i[1]);
  if(preg_match('/<textarea/',$f)){
    $v=$_POST[$n]==''?$i:$_POST[$n];
    $f=preg_replace('/<textarea(.*?)>(.*?)<\/textarea>/',
    '<textarea\\1>'.stripslashes(htmlentities($v)).'</textarea>',$f);
        if($Javascript){$f=preg_replace('/<textarea/',
        '<textarea>

You can strip the Javascript that automatically clears the initial value when the element gets the focus by not defining the global variable $Javascript.

The global variable $errorindicator can be a text or any HTML, for example an image. The content of this variable will be displayed before each missing mandatory element.

The CSS class added to each missing field is defined in the global variable $errorclass.

Mandatory elements get defined separated by a comma in a hidden field called "required":

&#60;input type=&#34;hidden&#34;
  name=&#34;required&#34;
  value=&#34;Name,SurName,live,message&#34; /&#62;

The initial value of the form element is defined by its ID. As IDs cannot contain spaces, you need to replace them with underscores. The function removes them automatically. If, for example, you want to display "Please enter your first name" as the initial value in a text box, use the corresponding ID:

&#60;input type=&#34;text&#34;
  name=&#34;name&#34;
  id=&#34;Please_enter_your_first_name&#34; /&#62;

The function adds hidden fields with the initial values to the form. For the "name" example, this would be:

&#60;input type=&#34;hidden&#34;
  name=&#34;nameinitvalue&#34;
  value=&#34;Please_enter_your_first_name&#34; /&#62;

The add() function takes care of the form drawing, the highlighting, and the setting of the initial value.

To use it in a PHP document, you wrap your form elements in it:

<form method="post" action="<?=$_SERVER['PHP_SELF']?>">
  <input type="hidden" name="required" value="Name,SurName,live,message" />
  <fieldset>
    <legend>Identification</legend>
      <label for="your_name">Name:</label>
        <?=add('<input type="text" name="Name"
         id="Your_Name" />')?><br />
      <label for="your_surname">Surname:</label>
        <?=add('<input type="text" name="SurName"
         id="Your_Surname" />')?> 
  </fieldset>
  <fieldset>
    <legend>Gender and age</legend>
    <label for="Age">Age:</label>
      <?=add('
      <select name="Age">
          <optgroup label="Non­Teen">
          <option value="5">Under 5</option>
          <option value="9">Five to Ten</option>
        </optgroup>
        <optgroup label="Teen">
          <option value="10">Aspiring Teen</option>
          <option value="15">Mid Teen</option>
          <option value="19">End Teen</option>
        </optgroup>
        <optgroup label="Twen">
          <option value="20">Aspiring Twen</option>
          <option value="25">Mid Twen</option>
          <option value="29">End Twen</option>
        </optgroup>
        <optgroup label="Above">
          <option value="30">30ies</option>
          <option value="40">40ies</option>
          <option value="over50">Above</option>
        </optgroup>
      </select>
      ')?>
    <strong>Gender:</strong>
      <?=add('<input type="radio" name="Gender" id="Male" 
      checked="checked" value="Male" />')?>
      <label for="Male">Male</label>
      <?=add('<input type="radio" name="Gender" id="Female"
       value="Female" />')?>
      <label for="Female">Female</label>
  </fieldset>
  <fieldset>
    <legend>Enter your message</legend>
      <p><?=add('<input type="checkbox" name="live" 
      id="live" />')?>
      <label for="live">Publish to live</label></p>
      <p><label for="your_message">Your Message:</label></p>
      <?=add('<textarea name="message" id="Your_message"
       cols="30" rows="10"></textarea>')?>
  </fieldset>
  <p align="right"><input type="submit" value="Send" /></p>
</form>

You need another function to strip these initial values once the form is filled and each mandatory field is filled with something else than its initial value.

Function 2: Checking the form

function check(){
  if ($_POST!=''){
    $sentarray=array();
    $tocheck=explode(',',$_POST['required']);
    $error[0]="Errors:";
    foreach ($tocheck as $t){if(!array_key_exists($t,$_POST)){
    $error[]=$t;}}
    foreach (array_keys($_POST) as $p){
      if(!preg_match('/initvalue/',$p) and 
      !preg_match('/required/',$p)){
        $sentarray[$p]=$_POST[$p]==
        $_POST[$p.'initvalue']?'':$_POST[$p];
      }
      foreach ($tocheck as $c){
        if ($p==$c and $sentarray[$p]==''){
          $error[]=$_POST[$p.'initvalue'];
        }
      }
    }
    return $error[1]==''?$sentarray:$error;  
    }
}

This function checks the required elements. If all have a value that is different from the initial value, it'll return an array containing only the necessary fields. All the generated initial value fields and the "required" field are stripped out.

If there was a mandatory field that is empty or still has the initial value, the resulting array will have a first element with the value "Errors:", and a list of all the missing fields as the other array elements.

To use the function, you could do something like this:

<?PHP
  $errorindicator='<img src="alert.gif" width="20" height="20" 
  alt="Alert" title="Indicator for missing form element" border="0" />';
  $errorclass="error";
  $Javascript=true;
  $results=check();
  if($results[0]=='Errors:'){
    
?>
  <h2>There has been an error:</h2>
  <p>You forgot to enter the following field(s)</p>
  <ul>
  <?PHP foreach ($results as $i=>$e){if ($i>0){
    echo "<li>$e</li>";
  }}?>
  </ul>
<?PHP 
  }else{
  // Add send functionality here
  }  
?>

That's it. To see the functions in all their glory, and download them with an example, go to the homepage. Updates and fixes will happen there and be announced in the comments below.

Currently employed in London as a Lead Front End Developer, Chris has been bouncing around the globe working for several agencies and companies. A web enthusiast from 1997 on workplaces include Munich, London, Santa Monica and San Francisco. More of Chris' writings can be found at http://icant.co.uk and he blogs at http://wait-till-i.com

Small bug with radio checked="checked"??

Submitted by steven_spencer on May 21, 2003 - 16:16.

In the example shown, I think the Male radio button should be checked by default, as it is being generated with a checked="checked" attribute. However, both radio buttons are unchecked.

login or register to post comments

potential fix for radio checked bug

Submitted by steven_spencer on May 21, 2003 - 16:39.

First line under case 'radio' changes to this: $f=$_POST[$n]==''?$f:preg_replace('/checked.*?\s/','',$f);

login or register to post comments

What browser are you using?

Submitted by codepo8 on May 22, 2003 - 02:19.

When you load the homepage none is checked and there is no "checked" generated. Once I check one of them it works fine though. On IE6, FIrebird and Opera...

login or register to post comments

checkbox fix

Submitted by M_A_R_C_O on May 27, 2003 - 01:12.

"Publish to live", if not checked returns an error "You forgot to enter the following field(s): live"

If I cut and paste the code and "run" it message isn't copied into the text area. If I try from this website it works. Is message display depenent on CSS?

Cheers,
*M

PS: I'd have loved meaningful names for variables... they help sometimes to understand

login or register to post comments

Can't reproduce the problem

Submitted by codepo8 on May 27, 2003 - 01:29.

Well, as "live" is a mandatory field (Name,SurName,live,message) not checking it naturally results in a message/error being displayed.

The re-display of the message is dependent on the <=add()?> being around the textarea tag. Could it be that you use an older version of PHP that does not support superglobals like $_POST?

Define "meaningful names for variables" please.

$errorindicator, $errorclass and $Javascript sound rather self-explanatory to me...

login or register to post comments

just my opinion

Submitted by M_A_R_C_O on May 27, 2003 - 01:48.

Someone 's missing the meaning of checkboxes then. An always checked checkbox is useless

$_POST is supported on my system

I'm talking about function add, it's quite cryptic to me; you wrote it, it's crystal clear to u. Anyway, it requires much more brain activity than needed to understand.

Don't be so ticklish, we're just talking about some code. Do you want it to be perfect? Accept critiques.
*M

login or register to post comments

Ah...

Submitted by codepo8 on May 27, 2003 - 05:04.

Yes, add() is a tad cryptic, as I wanted to keep it short for displaying and printing.

An always checked checkbox was only an example to show that this technique highlights checkboxes the right way, too. The form doesn't send the data anywhere, so it is useless as it is :-)

An example where that makes sense would be a "I have read the terms and conditions"

Critique is nice, and I have no problem with it, it just should be as easy to understand as variables should be :o)

The idea of this article is not that you dismember add(), but use it, and thus speeding up your form development. It is no rocket science, and anyone with some RegExp knowledge can do a similar one.

login or register to post comments

HTML encoding?

Submitted by tomgilder on May 30, 2003 - 22:52.

This code is riddled with cross-site-scripting problems. Try entering ">bleh into inputs and watch it go titsup. Not good.

Also, "Accessibility tools such as Bobby make it even worse, as they expect an initial value for each element" - that doesn't mean they are right. The WAI guideliens state you should provide an initial value (that does not mean value="" either) until UAs can cope with it. UAs *can* cope with it. The guidelines is no longer valid, at least in my opinion.

login or register to post comments

Cross scripting fixed

Submitted by codepo8 on June 2, 2003 - 03:00.

Check the homepage, I added a fix for the cross-scripting bit. 2 lines were changed The Bobby problem was explained above, however, sometimes you want to add an initial value to show the format necessary for an entry.

login or register to post comments

Select from mysql?

Submitted by tmeyer on June 10, 2003 - 05:43.

Did anybody got this to work with a select from a mysql-table like this one?

&#60;select name="cid" id="categorie"&#62;<br>
&#60;option value="" selected&#62;Select categorie&#60;/option&#62;<br>
&#60;?<br>
$query="SELECT cid,categorie FROM db_categorie ORDER BY categorie";<br>
$result=mysql_query($query);<br>
while(list($cid,$categorie)=mysql_fetch_row($result))<br>
{<br>
echo "&#60;option value='$cid'>$categorie
}?&#62;<br>
&#60;/select&#62;<br>

login or register to post comments

mySQL select

Submitted by mswitzer on June 11, 2003 - 09:16.

Try this - and remember well-formed html and xhtml has closing tags and quotes (double, not single) around attribute values

php processes single quoted strings faster than double quoted strings, so avoid double quotes around your echoed strings where possible.


<?php
$query
="SELECT cid,categorie FROM db_categorie ORDER BY categorie";
$result=mysql_query($query);
if(
$data = mysql_fetch_array($result)) {
?>
Select categorie
<?php
do {
echo
''.$categorie.''."\n";
while(
$data = mysql_fetch_array($result));
?>

login or register to post comments

A more complex approach

Submitted by skunk on June 17, 2003 - 15:17.

Inspired by this article, I took another look at the form validation problem. I've just released the first draft of my solution, which uses additional attributes on form tags to define validation logic which are stripped out by an XML parser before the form is displayed. Comments are welcome.

login or register to post comments

Good article:

Submitted by Aman on July 12, 2003 - 23:22.

The PHP Black Book describes some additional ways to cut down the time reqired to build forms using PHP.

login or register to post comments

Great Article

Submitted by duanelawrence on December 19, 2003 - 06:22.

This is great. I am still on the learning curve on PHP and web stuff and this is one of the best articles I have found on "form validation" in PHP. Duane Lawrence

login or register to post comments

How about an email function

Submitted by cal on August 10, 2004 - 19:15.

I like this script and would like to know if someone has a mod or would be willing to. What I'd really like is an easyform that tests answers (as this one does), then upon error = 0 it would email in html format the form with the answers in place. Any takers? I'm not able to get it to work.

login or register to post comments

How do i send to email

Submitted by trapman on December 10, 2004 - 12:07.

These scripts have helped me out a lot, but there is still one more thing I need and I'm sure others would be greatful too. How do I get the data sent from this form to either go to email or a file on the web server. Here is some script that I know of to have a very simple email form sent to email..
@extract($_POST);
$name = stripslashes($name);
$email = stripslashes($email);
$subject = stripslashes($subject);
$text = stripslashes($text);
mail('youremail@domain.com',$subject,$text,"From: $name ");
header("location:form.php");
The form.php you enter in the email data and click send, then it calls the above file(process.php) to send the data to email.

login or register to post comments

Can we choose to not display form after submit?

Submitted by jaredweb on January 4, 2005 - 14:00.

This form is quite amazing except for one little thing... When you input the correct data and the form accepts it as correct, it still shows the form blocl below. Is there a fix for this? It would be awfully nice and makes much more sense to me. I would imagine visitors would get easily confused if they see the form block back there after it's been correctly submitted. Thanks

login or register to post comments

Problem with presenting radio & checkbox id error

Submitted by TheFinnisher on January 29, 2005 - 21:02.

I am in the process of creating an online survey with form validation. Easyform was one of the better form tutorials and examples I was able to find online. The script does a terrific job in validating the form. However, there is a problem when reporting the errors for a radio button or checkbox form element.

For instance, if you change the checkbox id name from live to Go_Live in the example form, the hidden field is created properly:

< input type="checkbox" class="error" name="live" id="Go_Live">
< input type="hidden" class="error" name="liveinitvalue" value="Go Live">

HOWEVER!

The error reports that a field of "live" was left blank.

The same thing occurs for radio buttons.

This may not be a terrible flaw, BUT, consider this:

You have a checkbox name that you have abreviated because of length "intrestlvl" but you would really like to have the error report say. Question 48 Interest level in basketball. If the form submits an error saying, please fill in "intrestlvl"...the user may not be able to understand what item he missed. Except for the fact of showing it with the errorindicator.

Anyhow, I would greatly appreciate if someone knew how to fix this bug. I believe it has to do with the add($f) function in the easyform.php file.

Thank you!

login or register to post comments

How do I get a second form after a post

Submitted by yoki28 on October 27, 2005 - 19:11.

I'm wondering how I could get to another form? How would I program this? Please help someone!

login or register to post comments

Where is the home page?

Submitted by AdRock on August 20, 2007 - 20:34.

I have been looking for something like this for ages and I think it's great even though it's over 4 years old. What I would like to know is where is the home page for the fix?

login or register to post comments

The access keys for this page are: ALT (Control on a Mac) plus:

evolt.orgEvolt.org is an all-volunteer resource for web developers made up of a discussion list, a browser archive, and member-submitted articles. This article is the property of its author, please do not redistribute or use elsewhere without checking with the author.