SPSU WebMark
click for Brown's home page

PHP Arrays and Forms Handling

PHP Arrays

Like other PHP variables, elements of an array are dynamically typed. Not all elements of an array need be the same type, and the type of an element can be changed by a new assignment.

PHP arrays can have either integers or strings as subscripts. If an integer subscript is used, the PHP array behaves like those in other languages. We will discuss that application of PHP arrays first. When PHP arrays are used with integer subscripts, the lowest subscript is zero.

There are two ways to create an array: You can use the language construct array() to create an array from a list, or you can assign individual elements to the array. The following code fragments are equivalent:

$people = array('Bob','Carol','Ted','Alice');

$people[0]='Bob';
$people[1]='Carol';
$people[2]='Ted';
$people[3]='Alice';
If you assign a value to an array using an empty subscript, the next available integer value is used. The assignment $people[ ]='George'; will assign the value 'George' to $people[4] if issued when the array has been initialized as shown above.

Individual array elements can be accessed using their subscripts. The statement echo $people[2]; will print "Ted".

There is a foreach construct that will loop over the values in an array. Executing this code:

foreach($people as $x) {
  echo $x, ' ';    
} 
will print "Bob Carol Ted Alice " (assuming we haven't added George to the array). The loop executes once for each element in the array, and each element in turn is assigned to the variable $x.

The other way to use a PHP array is to think of the subscript as a key that can be used to retrieve data, similar to Perl's hash. In this case, the "subscript" will be a string. As with integer subscripts, there are two ways of assigning values to an array. The code fragments below are equivalent.

$cast = array('Carol' => 'Natalie Wood',
              'Bob' => 'Robert Culp',
              'Ted' => 'Elliott Gould',
              'Alice' => 'Dyan Cannon');

$cast['Carol'] = 'Natalie Wood';
$cast['Bob'] = 'Robert Culp';
$cast['Ted'] = 'Elliott Gould';
$cast['Alice'] = 'Dyan Cannon';
Arrays created in this way are manipulated using strings for subscripts. The statement echo $cast['Ted']; will print "Elliott Gould".

The foreach construct can be used to extract both subscripts and values.

foreach($cast as $role => $actor) {
  echo $role, ' is played by ', $actor,'<br />';
}
prints:
Carol is played by Natalie Wood
Bob is played by Robert Culp
Ted is played by Elliott Gould
Alice is played by Dyan Cannon
Using this form of foreach with an array with integer subscripts also works. The "key" part ($role above) will hold the subscript and the data part will hold the element value.

PHP arrays have order, and the order of arrays can be manipulated with sorting functions. You can read what the PHP documentation has to say about arrays here: http://www.php.net/manual/en/language.types.array.php.

Processing Forms with PHP

PHP predefines several variables that make it easy for the programmer to deal with forms. In earlier versions of PHP, form items were automatically defined in the receiving PHP program. For example, if you had a text area named "address" the PHP program that received the form would automatically define $address for you and load it with the contents of the text area. You may see examples of this if you study the PHP code of others, but this approach is now deprecated. Why are we telling you about it? Because it's a security risk. A malicious person could possibly "spoof" any variable in your PHP program by appending a name/value pair to a URL. If you extract data from an array, you know which variable assignments come from outside your program, and so are possibly tainted.

With that out of the way, let's get on to the right way to process forms data. Two of the predefined PHP variables are $_GET and $_POST. Both names start with a dollar sign and an underscore; the letters are all capitals. These are arrays that contain data passed by the GET and POST methods respectively. The array keys are the form item names and the array data elements contain the data from the form.

Suppose an HTML document contains the following form:

<form action="process_it.php" method="post">
User ID: <input type="text" name="userid"><br />
E-Mail: <input type="text" name="email"><br />
<input type="submit" value="Submit">
</form>
A portion of process_it.php might contain the following:
<?php
  $userid=$_POST['userid'];
  $email=$_POST['email'];
  echo "Hello, $userid!  Your e-mail address is $email.<br />";
?>
That's all there is to it. In fact, you can use $_POST['userid'] directly in most PHP statements, but not in echo. For most programs you'll find it easier to assign at least the frequently-used array elements to scalar variables as we did in the example.

If you had used method="get" in your form declaration, you would have used the $_GET array instead.

Periods are legal in HTML form control names, but not in PHP variable names. PHP overcomes this by automatically converting periods to underscores in form control names. Avoid confusion by not using periods in your form control names.

There are some special considerations for menus (defined with <select>), checkboxes, and radio buttons.

If a menu includes the multiple attribute on the select element, e.g. <select multiple> the user of the menu may select two or more of the choices. Unless you allow for this, you will get only the last of the selected options. To cause PHP to make all the selected choices available as an array, suffix your select name with a pair of square brackets, like this:

<form action="buy_snacks.php" method="post">
<select multiple name="snacks[ ]">
  <option value="coke">CocaCola</option>
  <option value="popcorn">Popcorn</option>
  <option value="peanuts">Peanuts</option>
</select>
</form>

If this form is sent to a PHP program, the value of $_POST['snacks'] will be an array. Note that the square brackets in the form control name aren't a part of the array key. You would process such a form like this:
<?php
$snacks = $_POST['snacks'];
// Note that $snacks will be an array.
foreach ($snacks as $s) {
  echo "$s<br />";
}
?>

Checkboxes return nothing (neither a name nor a value) if unchecked. If checked, a checkbox returns the content of the value attribute if one is present. A checkbox with no value attribute returns the value "on" if checked. If a checkbox is not checked, the corresponding element of $_POST or $_GET will not be defined. Assigning an undefined array element to a variable creates a variable with the type and value NULL. That means you can test checkboxes like this:

<?php
  $box1 = $_POST['box1'];
  if ($box1) echo 'Box 1 was checked.';
  else echo 'Box 1 was NOT checked.';
?>

The HTML specification allows two or more checkboxes to have the same name attribute. The idea is to group related choices where multiple values may be selected. Here's an example:

<form method="post">
I speak the following languages:
<input type="checkbox" name="lang" value="en">English<br />
<input type="checkbox" name="lang" value="fr">Français<br />
<input type="checkbox" name="lang" value="es">Español<br />
</form>
If this were processed as given, only the last checked value would be stored in the $_POST array. The solution is to add square brackets to the value of the name attribute, causing an array of values to be created.
<form method="post">
I speak the following languages:
<input type="checkbox" name="lang[ ]" value="en">English<br />
<input type="checkbox" name="lang[ ]" value="fr">Français<br />
<input type="checkbox" name="lang[ ]" value="es">Español<br />
</form>
You process such an array in the way shown above for multivalued menu options.

Radio buttons have multiple choices, but one and only one value is transmitted for each group. (A group of radio buttons are those with the same name attribute.) Here is an example:

<form method="post">
My preferred language is: 
<input type="radio" name="pref" value="en" checked>English<br />
<input type="radio" name="pref" value="fr">Français<br />
<input type="radio" name="pref" value="es">Español<br />
</form>
If no radio button of a group is checked, the action of the client browser is unpredictible. For that reason, you should always specify the checked attribute for one button of a group, assuring that a button will be checked when the form is transmitted.

PHP has other predefined variables, including $_SERVER that can provide information about the server and remote connection. $_SERVER['REQUEST_METHOD'] tells the request method used to access the page. (Presumably you already know that because you wrote the page with the form, right?)

All the predefined variables are "superglobals," which means they're available even in the scope of functions. You can read about the other PHP predefined variables here: http://www.php.net/manual/en/language.variables.predefined.php.

Creating Forms with PHP

You can create forms with ordinary HTML, but by using PHP, you can sometimes make form creation easier. Using PHP with a database will allow you to create forms that change on the next use if the value of the database changes. Of course, you can fill in text boxes and text areas with default values, but one of the most useful things you can do with PHP is to populate <option> tags with dynamic values to create drop-down menus that reflect the current values in a database.

Consider the $cast array from the first section of this paper. Here is a complete, although very simple HTML form that builds a drop-down menu from such an array. Selecting the actor's name sends the character's name as data because the character's name is used in the value= attribute.

<html>
<head>
<title>Select an Actor</title>
</head>
<body>
<h2>Select an Actor</h2>
<form action="query_string.cgi">
<select name="character">
<?php
$cast = array('Carol' => 'Natalie Wood',
              'Bob' => 'Robert Culp',
              'Ted' => 'Elliott Gould',
              'Alice' => 'Dyan Cannon');
foreach($cast as $role => $actor) {             
  echo "<option value=\"$role\">$actor</option>\n";
}
?>
</select>
<input type="submit" value="Find Role">
</body>
</html>
This form sends its data to query_string.cgi, the Perl program that decodes name/value pairs from forms. For this program, the name will always be "character" because that's what is coded in the <select> tag. The value will be the character played by the actor whose name we selected.

In "real life" this form would probably be more complicated, the processor would be something that does real work, and the array would have been filled from a database rather than with constant data.

Notice that the foreach that actually generates the <option> tags only occupies two lines, give or take a curly brace. There is one other thing to notice about the program above. The echo includes an escape sequence for a new line: \n. You might wonder why that's there since we're emitting HTML. It puts each <option> tag on a new line in the generated HTML so it's easy to see what is going on by viewing the HTML source from your browser. Not having extremely long lines makes debugging much easier.

GET, POST, and Idempotence

There is one other thing to say about HTML forms processing in general. In order to say it, we need a twenty-five cent word: idempotent. A function is idempotent if applying the function repeatedly does not change the result. Multiplication by one is idempotent. No matter how many times you multiply a number by one, it doesn't change.

The HTTP 1.1 protocol specifies that the GET method should be both safe, that is, free from side-effects, and idempotent. This gives browsers and proxies the freedom to cache responses to GET requests and to return subsequent, identical requests from the cache, never sending the request back to the server. You can read the relevant part of the specification at: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html.

The visible difference between POST and GET is that with GET, the form variables are encoded in the URL. The far more important, invisible difference is that if you use GET, your request might not get to the server at all.

If sending a form has side-effects, like placing an order or updating a database, you must use the POST method to be compliant with the standard.

Next: Database Access with PHP

Previous: A Gentle Introduction to PHP


Last updated: 2014-09-27 13:34  
Originally published: