Article

CGI::Application: A Simple, Extensible Web Framework

Page: 1 2 3 4 Next

Displaying the User Form

Creating the Template

As mentioned earlier, HTML::Template is supported by default, so our form will be quite simple:

 1  <!doctype html public "-//W3C//DTD HTML 4.0 Transitional//EN">  
 2  <html>  
 3  <head>  
 4  <title>Maintain Users</title>  
 5  </head>  
 6  <body>  
 7  <tmpl_include menu.tmpl><br><br>  
 8  <tmpl_var name=message>  
 9  <tmpl_if some_errors>There are errors in your form</tmpl_if>  
10  <form action="" method="post">  
11    <table>  
12      <tr>  
13        <td>Username<tmpl_unless user_id>*</tmpl_unless></td>  
14        <td><tmpl_unless user_id>  
15                        <input type="Text" name="username" size="15"  
16                            value="<tmpl_var name=username>">  
17                    <tmpl_var name=err_username>  
18                    <tmpl_else>  
19                        <tmpl_var name=username>  
20                    </tmpl_unless>  
21            </td>  
22      </tr>  
23      <tr>  
24        <td>First Name*</td>  
25        <td><input type="Text" name="first_name" size="15"  
26                value="<tmpl_var name=first_name>">  
27                <tmpl_var name=err_first_name></td>  
28      </tr>  
29      <tr>  
30        <td>Last Name*</td>  
31        <td><input type="Text" name="last_name" size="15"  
32                value="<tmpl_var name=last_name>">  
33                <tmpl_var name=err_last_name></td>  
34      </tr>  
35      <tr>  
36        <td>Email</td>  
37        <td><input type="Text" name="email" size="15"  
38                value="<tmpl_var name=email>">  
39                <tmpl_var name=err_email></td>  
40      </tr>  
41      <tr>  
42        <td>Password<tmpl_unless user_id>*</tmpl_unless></td>  
43        <td><input type="Password" name="password" size="15"  
44                value="<tmpl_var name=password>">  
45                <tmpl_var name=err_password> <tmpl_var name=err_user_id></td>  
46      </tr>  
47      <tr>  
48        <td>Repeat Password<tmpl_unless user_id>*</tmpl_unless></td>  
49        <td><input type="Password" name="password2" size="15"  
50                value="<tmpl_var name=password2>">  
51                <tmpl_var name=err_password2></td>  
52      </tr>  
53      <tr>  
54        <td>Receive Newsletter</td>  
55        <td><input type="Checkbox" name="receive_newsletter" value="y"  
56                <tmpl_var name=checked>></td>  
57      </tr>  
58      <tr>  
59        <td colspan="2"><input type="Submit" value="Save"></td>  
60      </tr>  
61    </table>  
62    <input type="Hidden" name="user_id" value="<tmpl_var name=user_id>">  
63    <input type="Hidden" name="rm" value="maintain_user">  
64  </form>  
65  </body>  
66  </html>

If you haven't encountered HTML::Template before, have a look at the previous article. The only differences between standard HTML and our template are the placeholders for the value attribute of the input tags (e.g. username) and the field error messages (e.g. err_username). The placeholders will be empty when we create new users, and populated with the appropriate details at runtime.

Points of interest include:

  • Line 7: We include a simple menu which has "create user" and "edit user" options.
  • Lines 14-21: If we're creating a new user, the user_id will be 0 (false) and we should display an input tag for the username. If we modify a user, we simple display the username. We also indicate mandatory fields with an asterisk. Some of these fields aren't mandatory when we edit a user, so we hide the asterisk if the user_id is not 0.
  • Line 63: When we submit the form, CGI::Application will invoke the run mode identified by the "rm" parameter.

Creating our First Run-mode Method

The display_user_form() method is pretty sparse:

 1  sub display_user_form {  
 2      my $self = shift;  
 3      my $errs = shift;  
 4      my $q    = $self->query;  
 5  
 6      my $user_id  = $q->param('user_id') || 0;  
 7      # If we have a user id, then get the user's details  
 8      $self->_retrieve_user_details($user_id) if ($user_id);  
 9  
10      # Process the template  
11      my $template = $self->load_tmpl('user_form.tmpl');  
12  
13      # Populate the template  
14      foreach my $form_val qw(username first_name last_name email message) {  
15          $template->param($form_val, $self->param($form_val) || '');  
16      }  
17  
18      $template->param('checked', 'checked')  
19          if ($self->param('receive_newsletter') eq 'y');  
20  
21      $template->param('user_id', $user_id);  
22      $template->param($errs) if $errs;  
23  
24      #Display the form  
25      return $template->output();  
26  }

Line 3: We can ignore this for now. It is used when we wish to display our validation errors, which I'll discuss later on.

Line 4: By default, CGI::Application uses the CGI module behind the scenes, and all the query parameters are available to the query method. We assign them to $q purely as a matter of convenience, since we only need to type $q->param to retrieve any of the parameters.

Line 6: Get the user_id from the submitted form. If there isn't one (i.e. we're creating a new user), set the id to zero.

Line 8: If we're updating a user (the user_id is not zero), then retrieve the user record.

Line 11: Load the template.

Lines 14-16: CGI::Application allows you to save application-wide parameters using the param method. We saved the user's details in the method called at line 8, and here we transfer these values to the template. Because HTTP is a stateless protocol, application parameters will not be accessible to subsequent requests. If you need persistent data, you should save the values in session variables.

Lines 18-22: Set the remaining template parameters. Line 22 sets any error messages that may be returned when validating the form. Validation is discussed later on.

Line 25: CGI::Application handles all output for us. We never issue the "print" command, nor do we output the HTTP headers directly. If you wish to modify the headers, you can use the header_type and header_prop methods.

Processing the Form Data

Let's consider a trivial version of the maintain_user method.

 1  sub maintain_user {  
 2      my $self = shift;  
 3      my $q    = $self->query;  
 4  
 5      if ($q->param('user_id') == 0) {  
 6          $self->_create_user();  
 7      } else {  
 8          $self->_update_user();  
 9      }  
10  
11      $self->param('message', 'User saved');  
12      $self->display_user_form();  
13  }

In this run mode, if a user_id of zero is submitted, it means that we will create a new user, otherwise we will update an existing user. We have two other methods, _create_user and _update_user, that will do the actual database-related work. But ultimately, we'll want to validate the data against a set of rules:

  • The username, first name and last name are compulsory
  • The passwords must match
  • The email isn't compulsory unless the user has elected to receive the newsletter
  • The email address must be of an email format
  • The username must be at least 6 alpha characters long, and at most 10 alpha characters

Validating forms can be a tedious task. Fortunately, we can use a plugin to do the heavy lifting for us.

If you liked this article, share the love:
Print-Friendly Version Suggest an Article

Sponsored Links

Follow SitePoint on...