This text is excerpted from CGI Programming 101 (2nd edition). Click here to order the book.

Text copyright © 2004 by Jacqueline Hamilton. All rights reserved. You may print one copy of this page for your personal use. You may not copy this material onto another website or into any other medium.

Chapter 5: Advanced Forms and Perl Control Structures

In the last chapter you learned how to decode form data, and mail it to yourself. However, one problem with the guestbook program is that it didn't do any error-checking or specialized processing. You might not want to get blank forms, or you may want to require certain fields to be filled out. You might also want to write a quiz or questionnaire, and have your program take different actions depending on the answers. All of these things require some more advanced processing of the form data, and that will usually involve using control structures in your Perl code.

Control structures include conditional statements, such as if/elsif/else blocks, as well as loops like foreach, for and while.

If Conditions

You've already seen if/elsif in action. The structure is always started by the word if, followed by a condition to be evaluated, then a pair of braces indicating the beginning and end of the code to be executed if the condition is true. The condition is enclosed in parentheses:

The condition statement can be anything that evaluates to true or false. In Perl, any string is true except the empty string and 0. Any number is true except 0. An undefined value (or undef) is false.You can also test whether a certain value equals something, or doesn't equal something, or is greater than or less than something. There are different conditional test operators, depending on whether the variable you want to test is a string or a number:

If it's a string test, you use the letter operators (eq, ne, lt, etc.), and if it's a numeric test, you use the symbols (==, !=, etc.). Also, if you are doing numeric tests, keep in mind that $x >= $y is not the same as $x => $y. Be sure to use the correct operator!

Here is an example of a numeric test. If $varname is greater than 23, the code inside the curly braces is executed:

If you need to have more than one condition, you can add elsif and else blocks:

The line breaks are not required; this example is just as valid:

You can join conditions together by using logical operators:

Logical Operators

Logical operators are evaluated from left to right. Precedence indicates which operator is evaluated first, in the event that more than one operator appears on one line. In a case like this:

condition2 && condition3 is evaluated first, then the result of that evaluation is used in the || evaluation.

and and or work the same way as && and ||, although they have lower precedence than their symbolic counterparts.

Unless

unless is similar to if. Let's say you wanted to execute code only if a certain condition were false. You could do something like this:

The same test can be done using unless:

There is no "elseunless", but you can use an else clause:

Validating Form Data

You should always validate data submitted on a form; that is, check to see that the form fields aren't blank, and that the data submitted is in the format you expected. This is typically done with if/elsif blocks.

Here are some examples. This condition checks to see if the "name" field isn't blank:

You can also test multiple fields at the same time:

The above code will return an error if either the name or email fields are left blank.

param('fieldname') always returns one of the following:

If your form has more than one field containing the same fieldname, then the values are stored sequentially in an array, accessed by param('fieldname').

You should always validate all form data — even fields that are submitted as hidden fields in your form. Don't assume that your form is always the one calling your program. Any external site can send data to your CGI. Never trust form input data.

Looping

Loops allow you to repeat code for as long as a condition is met. Perl has several loop control structures: foreach, for, while and until.

Foreach Loops

foreach iterates through a list of values:

This loops through each element of @arrayname, setting $i to the current array element for each pass through the loop. You may omit the loop variable $i:

This sets the special Perl variable $_ to each array element. $_ does not need to be declared (it's part of the Perl language) and its scope localized to the loop itself.

For Loops

Perl also supports C-style for loops:

The for statement uses a 3-part conditional: the loop initializer; the loop condition (how long to run the loop); and the loop re-initializer (what to do at the end of each iteration of the loop). In the above example, the loop initializes with $i being set to 1. The loop will run for as long as $i is less than 23, and at the end of each iteration $i is incremented by 1 using the auto-increment operator (++).

The conditional expressions are optional. You can do infinite loops by omitting all three conditions:

You can also write infinite loops with while.

While Loops

A while loop executes as long as particular condition is true:

Until Loops

until is the reverse of while. It executes as long as a particular condition is NOT true:

Infinite Loops

An infinite loop is usually written like so:

Obviously unless you want your program to run forever, you'll need some way to break out of these infinite loops. We'll look at breaking next.

Breaking from Loops

There are several ways to break from a loop. To stop the current loop iteration (and move on to the next one), use the next command:

This example prints the numbers from 1 to 20, except for the number 13. When it reaches 13, it skips to the next iteration of the loop.

To break out of a loop entirely, use the last command:

This example prints the numbers from 1 to 12, then terminates the loop when it reaches 13.

next and last only effect the innermost loop structure, so if you have something like this:

The last command only terminates the innermost loop. If you want to break out of the outer loop, you need to use loop labels:

The loop label is a string that appears before the loop command (foreach, for, or while). In this example we used OUTER as the label for the outer foreach loop and INNER for the inner loop label.

Now that you've seen the various types of Perl control structures, let's look at how to apply them to handling advanced form data.

Handling Checkboxes

Checkboxes allow the viewer to select one or more options on a form. If you assign each checkbox field a different name, you can print them the same way you'd print any form field using param('fieldname').

Here is the HTML code for a set of checkboxes:

Working example: http://www.cgi101.com/book/ch5/colors.html

This example lets the visitor pick as many options as they want — or none, if they prefer. Since this example uses a different field name for each checkbox, you can test it using param:

Source code: http://www.cgi101.com/book/ch5/colors-cgi.html

Since we set the value of each checkbox to 1 (a true value), we didn't need to actually see if param($color) was equal to anything — if the box is checked, its true. If it's not checked, then param($color) is undefined and therefore not true.

The other way you could code this form is to set each checkbox name to the same name, and use a different value for each checkbox:

Working example: http://www.cgi101.com/book/ch5/colors2.html

param('color') returns a list of the selected checkboxes, which you can then store in an array. Here is how you'd use it in your CGI program:

Source code: http://www.cgi101.com/book/ch5/colors2-cgi.html

Handling Radio Buttons

Radio buttons are similar to checkboxes in that you can have several buttons, but the difference is that the viewer can only pick one choice. As with our last checkbox example, the group of related radio buttons must all have the same name, and different values:

Working example: http://www.cgi101.com/book/ch5/colors3.html

Since the viewer can only choose one item from a set of radio buttons, param('color') will be the color that was picked:

Source code: http://www.cgi101.com/book/ch5/colors3-cgi.html

It's usually best to set the values of radio buttons to something meaningful; this allows you to print out the button name and its value, without having to store another list inside your CGI program. But if your buttons have lengthy values, or values unsuitable for storing in the value field, you can set each value to an abbreviation, then define a hash in your CGI program where the hash keys correspond to the abbreviations. The hash values can then contain longer data.

Let's try it. Create a new HTML form called colors4.html:

Program 5-1: colors4.html - Favorite Colors HTML Form

Working example: http://www.cgi101.com/book/ch5/colors4.html

Next create colors4.cgi. This example not only prints out the color you picked, but also sets the page background to that color. The %colors hash stores the various RGB hex values for each color. The hex value for the selected color is then passed to CGI.pm's start_html function as the bgcolor (background color) parameter.

Program 5-2: colors4.cgi - Favorite Colors Program


Source code: http://www.cgi101.com/book/ch5/colors4-cgi.html

Handling SELECT Fields

SELECT fields are handled almost the same way as radio buttons. A SELECT field is a pull-down menu with one or more choices. Unless you specify a multiple select (see below), the viewer can only choose one option. Here is the HTML for creating a SELECT field:

Working example: http://www.cgi101.com/book/ch5/colors5.html

As with radio buttons, you access the selection in your CGI program using param('color'):

Source code: http://www.cgi101.com/book/ch5/colors5-cgi.html

Multiple-choice SELECTs

Multiple SELECTs allow the viewer to choose more than one option from the list, usually by option-clicking or control-clicking on the options they want. Here is the HTML for a multiple SELECT:

In your CGI program, param('color') returns a list of the selected values, just as it did when we had multiple checkboxes of the same name:

So now you've seen every type of form element (except for file-uploads, which we'll look at in Chapter 14), and in every case you've seen that CGI.pm's param function returns the value (or values) from each form field. The value returned by param is always a list, but for text, textarea, password, radio, and single select fields you can use it in a scalar context. For checkboxes and multiple select fields, you use it in an array context.

In the next chapter we'll learn how to read and write data files, so you'll be able to save and analyze the data collected by your forms.

Resources

Visit http://www.cgi101.com/book/ch5/ for source code and links from this chapter.

Previous Contents Next

 


Table of Contents | Order the Book | CGI101 Home