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.
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: </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 ###############################################
?>
|