Helping ordinary people create extraordinary websites!

Creating a PHP Form

By Darren W. Hedlund
2005-06-20

Creating a PHP Form

Extracting form variables when programming in Perl is a real task. The variables can be extracted fairly painlessly using the CGI.pm modules, but there is a lot of work going on under the hood. In PHP form variables just spring to life. If a form has an input statement.

<input type="text" name="FirstName">
we can just simply use $FirstName in our script. However, this wonderful shortcut is of no value if we don't know the contents of the name clauses from the submitted form. In a generalized form handler, we must deal with $FirstName even though we don't know the name of the variable.

Fortunately, PHP has an associative array containing all the name/values pairs contained in a form submission. Actually PHP has two arrays, $HTTP_POST_VARS and $HTTP_GET_VARS. As you might expect, the first is populated with a form submission cybercms_problemcybercms_problemusing the post method while the latter is populated with get method submissions.

The $REQUEST_METHOD environment variable normally contains a value of either get or post if the script was called from a form. However, some older servers may not set this variable so we'll detect which associative array is loaded to determine the form's submission method.

The function GetFormData performs two tasks. It returns the appropriate value Post or Get as the first positional parameter. The second parameter is an associative array containing the submitted data, including hidden fields. Once the method determination is ascertained, this scheme frees the script from any additional get/post consideration.

function GetFormData(&$Method,&$FormVariables) {
  # Determine if the form used the post or get method and return in $Method
  # Return the form's variables as an associative array containing the
  # set of Name - Value pairs.

  global $HTTP_POST_VARS, $HTTP_GET_VARS;
  # POST or GET method used when submitting the form?
  $Method = (isset($HTTP_POST_VARS)) ? "Post" : "Get";
  # Load the $FormVariables associative array from appropriate array
  $FormVariables = ($Method == "Post") ?
       $HTTP_POST_VARS : # Post Method Used
       $HTTP_GET_VARS;   # Get Method Used
} # End of function GetFormData
The two parameters are passed by reference, note the & before the $ used for both variables. The function call would use the template:

GetFormData($Method, $FormVariables);
You will also notice the Phanatic's penchant for the ternary conditional format.

$ReceivingVariable = (Condition) ? TrueAssignment : FalseAssignment;
A form element by any other name
Displaying form values presents a three-fold problem:

traversing the $FormVariables array;
traversing any form element having multiple values; and
culling out HIDDEN form values.
We'll cover these in turn.

Let's initially explore the first two problems. An associative array is a set of key/value pairs. The key portion of the $FormVariables array represents the form component's name clause. Conversely, the value portion represents what the user inputs or the value clause in a hidden field.

PHP has a foreach array traversal function. The foreach construct can be used for associative or indexed arrays. Our form mailer needs a function to take an associative array as input, traverse the array -- formatting the display of the array on the fly, and finally, return the formatted HTML. The following is the code snippet for dumping the $FormVariables, which is an image of either the $HTTP_GET-VARS or $HTTP_POST_VARS array. The same function can be employed to display other associative arrays variables such as environment values.

Both of the function's required parameters are called by reference. The first parameter is the associative array to be displayed while the second parameter returns the formatted HTML.

function DisplayArrayVariables(&$FormVariables,&$HTMLVariables) {
  $HTMLVariables = "";
  foreach ($FormVariables as $Name=>$Value) {
      $HTMLVariables .= "<tr><td align=\"right\"><b>$Name:&nbsp;</b></td>\n";
      if (gettype($Value) == "array") {
          $ArrayComponent = "";
          foreach ($Value as $ArrayElement) {
              $ArrayComponents .= "$ArrayElement, ";
          } # End of foreach ($Value as $ArrayElement)
      $Value = substr($ArrayComponents,0,strlen($ArrayComponents)-2);
    } # End of if (gettype($Value) == "array")
    $HTMLVariables .= "<td><b>$Value</b></td></tr>\n";
  } # End of foreach ($FormVariables as $Name=>$Value)
  $HTMLVariables = "<table>\n$HTMLVariables\n</table>\n";
} # End of function DisplayArrayVariables
Hidden fields
The soul of a generic form handler is the script's ability to perform a variety of optional tasks as selected by the designer of the form. The various options and parameters are passed to the script as hidden fields. Quite simply, a hidden field has a predetermined value assigned by the form's designer, but the end-user of the form never sees the hidden fields unless they look at the document's source code.

The form handler has only one required hidden field: the e-mail address of the designated recipient receiving the formatted output. The HTML code might be

<input type="hidden" name="Recipient" value="toc@aol.com">
The hidden fields must appear between the <form> and </form> tags. As you might suspect, once we're in the script, the variable $Recipient contains the value toc@aol.com.

Once arriving in the CGI script, the name/value pairs from any hidden fields are indistinguishable from user-supplied data. We need a method to determine which of the form's supplied field are control variables and which are user variables. To distinguish between the two types, let's call them system variables and user variables. System variables and values are created by the form designer. User values are those entered into the form by the user.

Separating the system and user data is a three-part process. First, select a group of names than can only be used for system variables. Second, build an associative array containing name(key) parts representing possible system variable names. Additionally, default values for those keys, if any, are then initialized. The Phanatic has his own naming conventions as you can see from the scripts. He prefers running variable names together and starting each name portion with a capital letter, something like FirstName. However, even the Phanatic is willing to recognize that others may have different naming preferences. Use whatever convention you like, just be consistent. How about this range of name values:

all caps;
all ;ower case;
proper Case (First letter of each word capitalized);
words separated by a space, dash, or underscore.
In other words, FirsName, FIRSTNAME, firstname, first name, First-Name, First Name, and First_Name should all be recognized as the same system variable name, namely firstname. Here is a snippet from the StartUp function:

$SystemVariables = array(
  # The action variable determines the script's role.
  #  "M" is mail results to recipient
  #  "T" test form by displaying form, system, and environment variables
  #  "A" mail results to recipient and acknowledgment to submitter

  action=>"M",
  allownamealias=>True,               # Allow name aliasing
  recipient=>"",                      # Email recipient - only required hidden field
  subject=>"Form Submission",         # Email subject
 # Cosmetic properties
  bgcolor=>"WHITE",           # Background color
To accomplish the required naming flexibility, the keys of the associated array are all specified as lower case with spaces, dashes, and underscores squeezed out. Now onto the second part, separating the system and user variables.

To peek ahead a little, the allownamealias field is set to either true or false indicating whether name aliases are to be allowed. Maybe you don't want FirstName and first-name to be the same field.

In an earlier function we placed the form's output into an associative array called $FormVariables. What we want to do now is traverse the $FormVariable array and transfer any system variables into the $SystemVariable array. In addition, we want to delete the system variable information from the $FormVariables array. Since we're now experts at traversing an associative array, let jump in.

foreach ($FormVariables as $Name=>$Value)
Remember, the $Name value of a system variable can be based on several different conventions. First, we have to convert the contents to conform to the values loaded in the StartUp function. Then we test the converted name by seeing if the converted value is a key value in the $SystemVariables array. The next two statements perform the conversion. The first uses a Perl regular expression to replace blanks, dashes, and underscores with a null value. The second converts the result to all lower case.

# Replace blanks, dashes, and underscores with nothing.
$TestKey = preg_replace("/( |-|_)/","",$Value);
$TestKey = strtolower($TestKey);
The remainder of the function then determines if $TestKey (the converted value) resides in the $SystemVariables array. If so, it inserts the passed value into the array, overwriting any default value. If it is a system variable the name/value pair in the $FormVariable array are removed.

if (isset($SystemVariables[$TestKey])) { # Is it a system variable?
  $SystemVariables[$TestKey] = $Value;   # Use it's value if yes
  unset($FormVariables[$Name]);          # Remove it from $FormVariables
} # End of if (isset($SystemVariables[$TestKey]))
Summary
We're well on our way with our generic form process script but, alas, were running out of space. Let's wrap it up for now and add the bells and whistles next time. We'll also add some field validation in the next episode.

DEMO PHP FORM:

<?PHP

MakeHTMLtop("Form Series","Example Two");

empty($FirstPass) ?          # First pass if empty
  ShowForm() :               # Display the form if first pass
  $Errors = CheckResults($ErrorArray); # Check results if not first pass

($Errors) ? # Are there form processing errors?
  DisplayErrors($ErrorArray) : # Display Errors
  ShowResults();               # Display Results

exit; # All done

############################## Program Functions ##############################
# Function CheckResults #######################################################
function CheckResults(&$ErrorArray) {
  # Return 0 if no errors and 1 if there are errors
  global $FirstName, $LastName, $Gender, $City, $State,
  $Comments, $OperatingSystem, $FavoriteLanguage;
  $ErrorArray = array();
  $ErrorsPresent = 1; $NoErrors = 0;
 
  if (!$FirstName) $ErrorArray[] = "No first name entered";
  if (!$LastName)  $ErrorArray[] = "No last name entered";
  if (!$City)      $ErrorArray[] = "No city entered";
  if (!$Gender)    $ErrorArray[] = "Gender not selected";
  if (!$Comments)  $ErrorArray[] = "No comment entered";
  if (!$FavoriteLanguage) $ErrorArray[] =
    "Your favorite language not selected";
  $OScount = count($OperatingSystem);
  if (!$OScount) $ErrorArray[] = "Select at least one Operating System";
  $ErrorCount = count($ErrorArray);
  return ($ErrorCount) ? $ErrorsPresent : $NoErrors ;
} # End of function CheckResults ##############################################

#Function DisplayErrors #######################################################
function DisplayErrors(&$ErrorArray) {
 
print<<<StartErrors
  <H2><FONT COLOR="BLUE">There were form entry errors</FONT></H1>
<TABLE>
<TR>
  <TD><B>
  <UL>
StartErrors;

    foreach ($ErrorArray as $Error) {
       echo "<LI>$Error\n";
    } # End of foreach ($ErrorArray as $Error)

print<<<StopErrors
</UL>
<H2><FONT COLOR="BLUE">
  Please fix errors on the form below and resubmit</FONT></H2></B></TD>
</TR>
</TABLE>
StopErrors;

ShowForm();

} # End of function DisplayErrors #############################################

# Function MakeCheckBoxes #####################################################
function MakeCheckBoxes($Name,$PromptsAndValues,$Selected) {
   $ArrayCount = count($PromptsAndValues);
   for($Index=0;$Index<$ArrayCount;$Index++) {
     $String .=<<<STRING
     $PromptsAndValues[$Index]: <INPUT TYPE="CHECKBOX" NAME="$Name
STRING;
     $String .= ($ArrayCount>1) ? "[$Index]" : "";
     $String .= '"';
     $String .= "\n    VALUE=\"$PromptsAndValues[$Index]\"";
     $String .= ($Selected[$Index]) ? " CHECKED>" : ">";
     $String .= "\n";
   } # End of for ($Index=0;$Index<count($PromptsAndValues);$Index++)
   return chop($String);
} # End of function MakeCheckBoxes ############################################

# Function MakeHTMLtop ########################################################
function MakeHTMLtop($Title,$Heading) {
print<<<HTMLtop
<HTML>
<HEAD>
  <TITLE>$Title - $Heading</TITLE>
</HEAD>
<BODY>
<B>
<CENTER>
<H1><FONT COLOR="RED">$Title</FONT> -
  <FONT COLOR="BLUE">$Heading</FONT></H1>
HTMLtop;
} # End of function MakeHTMLtop ###############################################

# Function MakeRadioButtons() #################################################
function MakeRadioButtons($Name,$Current,
   $Values=array(1,0),$Prompt=array("Yes","No")) {

/* This function returns a string containing a formatted set of radio
    buttons. There are two required parameters and two optional parameters.
    The first positional parameter the value used for the NAME= parameter.
    The second positional parameter is the current value of the bottom
    variable. Simply pass the variable containing the current value. The
    third parameter (optional) is an array of possible values. The default
    is (1,0). The last parameter (optional) is an array of prompts. The
    default is ("Yes","No"). The relative position in the array should
    correspond with the values array. If the function is called with:

    MakeRadioButtons("Gender","Male",array("M","F"),array("Male:","Female:"));
    the following would be returned:
    Male: <INPUT TYPE="RADIO" NAME="Gender" VALUE="M" Checked>
    Female: <INPUT TYPE="RADIO" NAME="Gender" VALUE="F">

    If the call was:
    MakeRadioButtons("Married","1") the returned string would be:
    Yes: <INPUT TYPE="RADIO" NAME="Married" VALUE="1" Checked>
    No: <INPUT TYPE="RADIO" NAME="Married" VALUE="0">
*/

   for($Index=0;$Index<count($Prompt);$Index++) {
     $String .=<<<STRING
     $Prompt[$Index]: <INPUT TYPE="RADIO" NAME="$Name"
    VALUE="$Values[$Index]"
STRING;
     $String .= ($Prompt[$Index]==$Current) ? " Checked>" : ">";
     $String .= "\n";
   } # End of for ($Index=0;$Index<count($Name);$Index++)
   return chop($String);
} # End of function MakeRadioButtons ##########################################

# Function MakeStateDropMenu ##################################################
function MakeStateDropMenu($Name,$Selected="") {

/* This function build a select menu of US states, posessions, and APOs.
   There is one required parameter, the name used for the NAME parameter.
   There is one optional parameter, the name of the state to be used as
   a default. If the second parameter is not passed
*/

$DropMenu=<<<DropMenu
<SELECT NAME="$Name" SIZE="1">
  <OPTION VALUE="AL">Alabama</OPTION>
  <OPTION VALUE="AK">Alaska</OPTION>
  <OPTION VALUE="AS">American Samoa</OPTION>
  <OPTION VALUE="AZ">Arizona</OPTION>
  <OPTION VALUE="AR">Arkansas</OPTION>
  <OPTION VALUE="CA">California</OPTION>
  <OPTION VALUE="CO">Colorado</OPTION>
  <OPTION VALUE="CT">Connecticut</OPTION>
  <OPTION VALUE="DC">Washington D.C.</OPTION>
  <OPTION VALUE="DE">Delaware</OPTION>
  <OPTION VALUE="FL">Florida</OPTION>
  <OPTION VALUE="FM">Fed States of Micronesia</OPTION>
  <OPTION VALUE="GA">Georgia</OPTION>
  <OPTION VALUE="GU">Guam</OPTION>
  <OPTION VALUE="HI">Hawaii</OPTION>
  <OPTION VALUE="ID">Idaho</OPTION>
  <OPTION VALUE="IL">Illinois</OPTION>
  <OPTION VALUE="IN">Indiana</OPTION>
  <OPTION VALUE="IA">Iowa</OPTION>
  <OPTION VALUE="KS">Kansas</OPTION>
  <OPTION VALUE="KY">Kentucky</OPTION>
  <OPTION VALUE="LA">Louisiana</OPTION>
  <OPTION VALUE="ME">Maine</OPTION>
  <OPTION VALUE="MP">Marianas Pacific</OPTION>
  <OPTION VALUE="MH">Marshall Islands</OPTION>
  <OPTION VALUE="MD">Maryland</OPTION>
  <OPTION VALUE="MA">Massachusetts</OPTION>
  <OPTION VALUE="MI">Michigan</OPTION>
  <OPTION VALUE="MN">Minnesota</OPTION>
  <OPTION VALUE="MS">Mississippi</OPTION>
  <OPTION VALUE="MO">Missouri</OPTION>
  <OPTION VALUE="MT">Montana</OPTION>
  <OPTION VALUE="NE">Nebraska</OPTION>
  <OPTION VALUE="NV">Nevada</OPTION>
  <OPTION VALUE="NH">New Hampshire</OPTION>
  <OPTION VALUE="NJ">New Jersey</OPTION>
  <OPTION VALUE="NM">New Mexico</OPTION>
  <OPTION VALUE="NY">New York</OPTION>
  <OPTION VALUE="NC">North Carolina</OPTION>
  <OPTION VALUE="ND">North Dakota</OPTION>
  <OPTION VALUE="OH">Ohio</OPTION>
  <OPTION VALUE="OK">Oklahoma</OPTION>
  <OPTION VALUE="OR">Oregon</OPTION>
  <OPTION VALUE="PA">Pennsylvania</OPTION>
  <OPTION VALUE="PR">Puerto Rico</OPTION>
  <OPTION VALUE="RI">Rhode Island</OPTION>
  <OPTION VALUE="SC">South Carolina</OPTION>
  <OPTION VALUE="SD">South Dakota</OPTION>
  <OPTION VALUE="TN">Tennessee</OPTION>
  <OPTION VALUE="TX">Texas</OPTION>
  <OPTION VALUE="UT">Utah</OPTION>
  <OPTION VALUE="VT">Vermont</OPTION>
  <OPTION VALUE="VA">Virginia</OPTION>
  <OPTION VALUE="VI">Virgin Islands (U.S.)</OPTION>
  <OPTION VALUE="WA">Washington</OPTION>
  <OPTION VALUE="WV">West Virginia</OPTION>
  <OPTION VALUE="WI">Wisconsin</OPTION>
  <OPTION VALUE="WY">Wyoming</OPTION>
  <OPTION VALUE="AA">AA-APO/FPO</OPTION>
  <OPTION VALUE="AE">AE-APO/FPO</OPTION>
  <OPTION VALUE="AP">AP-APO/FPO</OPTION>
</SELECT>

DropMenu;
if ($Selected) {
  $DropMenu = preg_replace("|\"$Selected\">*|","\"$Selected\" SELECTED>",$DropMenu);
} # if ($Selected)
return $DropMenu;

} # End of function MakeStateDropMenu #########################################

# Function ShowForm() #########################################################
function ShowForm() {
  global $PHP_SELF; # The path and name of this file
  global $FirstName, $LastName, $Gender, $City, $State,
  $Comments, $OperatingSystem, $FavoriteLanguage;
  $Comments = stripslashes($Comments);

  $Selected = ($State) ? $State : "NJ";
  $StateDropMenu = MakeStateDropMenu("State",$Selected);
  $GenderButtons =
    MakeRadioButtons("Gender","$Gender",array("Male","Female"),array("Male","Female"));
  $FavoriteLanguageButtons =
    MakeRadioButtons("FavoriteLanguage","$FavoriteLanguage",
        array("PHP","Perl","C++","Other"),
        array("PHP","Perl","C++","Other"));
  $OperatingSystemBoxes = MakeCheckBoxes(
    "OperatingSystem",array("Unix","Linux","Windows 2000","Windows 9x","Other"),
     $OperatingSystem); # Last parameter is an array
#    array("Value1","Value2") if last parameter is an array of constants
#  $OneBox = MakeCheckBoxes("OneBox",array("Unix"),array("Unix"));

#<FORM ACTION="test.php" METHOD="POST">
$HTML=<<<HTML
<CENTER>

<FORM ACTION="process-form.php" METHOD="Get">
<INPUT TYPE="HIDDEN" NAME="FirstPass" VALUE="No">
<INPUT TYPE="HIDDEN" NAME="Recipient" VALUE="toc@aol.com">
<INPUT TYPE="HIDDEN" NAME="TextColor" VALUE="BLUE">
<INPUT TYPE="HIDDEN" NAME="ReturnLinkURL" VALUE="http://www.google.com">
<INPUT TYPE="HIDDEN" NAME="ReturnLinkTitle" VALUE="ATS Home Page">
<INPUT TYPE="HIDDEN" NAME="Action" VALUE="T">
<INPUT TYPE="HIDDEN" NAME="Recipient" VALUE=toc@aol.com>
<TABLE>
<TR>
 <TD ALIGN="RIGHT"><B>First Name:</B></TD>
 <TD><INPUT TYPE="Text" NAME="FirstName" VALUE="$FirstName"></TD>
 <TD ALIGN="RIGHT"><B>Last Name:</B></TD>
 <TD><INPUT TYPE="Text" NAME="LastName" VALUE="$LastName"></TD>
</TR>
<TR>
 <TD ALIGN="RIGHT"><B>City:</B></TD>
 <TD><INPUT TYPE="Text" NAME="City" VALUE="$City"></TD>
 <TD ALIGN="RIGHT"><B>State:</B></TD>
 <TD>$StateDropMenu</TD>
</TR>
<TR>
 <TD COLSPAN="2" ALIGN="RIGHT"><B>Your Gender?</B11/13/00></TD>
 <TD COLSPAN="2"><B>$GenderButtons</B></TD>
</TR>
<TR>
  <TD COLSPAN="2" ALIGN="RIGHT"><B>
    Your favorite Web programming language?</B></TD>
  <TD COLSPAN="2"><B>$FavoriteLanguageButtons
    </B></TD>
</TR>
<TR>
  <TD COLSPAN="4" ALIGN="CENTER"><B><FONT COLOR="BLUE" SIZE="+1">
    What Operating Systems have you used? Check all that apply.</FONT><B></TD>
</TR>
<TR>
  <TD COLSPAN="4" ALIGN="CENTER"><B>
    $OperatingSystemBoxes
    <BR>
    $OneBox<B></TD>
</TR>
<TR>
  <TD COLSPAN="4" ALIGN="CENTER"><B><FONT COLOR="BLUE" SIZE="+1">
    What do you think are PHP strengths and weaknesses?</FONT><B></TD>
</TR>
<TR>
  <TD COLSPAN="4" ALIGN="CENTER">
  <TEXTAREA COLS="60" ROWS="4" NAME="Comments">$Comments</TEXTAREA></TD>
</TR>
<TR>
  <TD COLSPAN="4" ALIGN="CENTER">
  <INPUT TYPE="Submit" VALUE="Submit Now"></TD>
</TR>
</TABLE>
</FORM>
</CENTER>
</B>
</BODY>
</HTML>
HTML;
echo $HTML;
exit;
} # End of function ShowForm ##################################################

# Function ShowResults () #####################################################
function ShowResults () {
  global $HTTP_USER_AGENT, $FirstName, $LastName, $Gender, $City, $State,
  $Comments, $OperatingSystem, $FavoriteLanguage;
  $Comments = nl2br($Comments);
  $Comments = stripslashes($Comments);
  $OSchoices = join(", ",$OperatingSystem);

$FormResults=<<<FormResults
Thanks for your submission:
<P>
<TABLE>
<TR>
  <TD ALIGN="RIGHT"><B>Your Name: </B></TD>
  <TD><B><FONT COLOR="RED" SIZE="+1">$FirstName $LastName</FONT></B></TD>
</TR>
<TR>
  <TD ALIGN="RIGHT"><B>Your Address: </B></TD>
  <TD><B><FONT COLOR="RED" SIZE="+1">$City, $State</FONT></B></TD>
</TR>
<TR>
  <TD ALIGN="RIGHT"><B>Your Gender: </B></TD>
  <TD><B><FONT COLOR="RED" SIZE="+1">$Gender</B></FONT></TD>
</TR>
<TR>
  <TD ALIGN="RIGHT"><B>
    Favorite Programming Language: </B></TD>
    <TD><B><FONT COLOR="RED" SIZE="+1">$FavoriteLanguage</FONT></B></TD>
</TR>
<TR>
  <TD COLSPAN="2" ALIGN="CENTER"><B>Operating System Used: </B></TD>
</TR>
<TR>
  <TD COLSPAN="2" ALIGN="CENTER"><B><FONT COLOR="RED" SIZE="+1">
    $OSchoices</FONT></B></TD>
</TR>
<TR>
  <TD COLSPAN="2" ALIGN="CENTER"><B>Your Comments About PHP</B></TD>
</TR>
<TR>
  <TD COLSPAN="2" ALIGN="CENTER"><B>
<FONT COLOR="RED" SIZE="+1">
$Comments
</FONT>
<BR>
are appreciated.</B></TD>
</TR>
<TR>
  <TD COLSPAN="2" ALIGN="CENTER"><B>
Pleased to see you are using:
<BR>
<FONT COLOR="BLUE" SIZE="+1">
  $HTTP_USER_AGENT</FONT></B></TD>
</TR>
</TABLE>
FormResults;
print $FormResults;
} # End of function ShowResults ###############################################

?>




Tutorial pages:
  • Creating a PHP Form

  Votes

You might also want to check these out:


Leave a Comment on "Creating a PHP Form"
You must be logged in to post a comment.

Link to This Tutorial Page!


GET OUR NEWSLETTERS