Perl CGI  «Prev  Next»

Lesson 7Processing States using Perl CGI
ObjectiveMore with the state-machine Guestbook

Understand how States are Processed in Guestbook Example

This lesson continues to use the guestbook example discussed in the previous lesson.
You may want to refer to your printed copy or print another to refer to during this lesson. We will also be refering to the following htmlp files:
error.htmlp (Perl Example)
<!-- $filename -->

<table>
  <tr><td width=20 height=30>
  <tr><td><td>

   <h3>Error:</h3>
   <p>$error

<form action="$callback" method=POST>

<p>
<input type=submit value=" Continue ">
<input type=hidden name=name value=$name>
<input type=hidden name=wherefor value=$wherefor>
<input type=hidden name=message value=$message>
<input type=hidden name=state value=edit>

</form>

  <tr><td height=30>
</table>

footer.htmlp
<!-- $filename -->

<hr noshade size=1 width=300 align=left>
<small>
Based on the Magic Guestbook by 
<a href="http://www.weinman.com/wew/">Bill</a>
<a href="http://www.weinman.com/">Weinman</a>
</small> <br>
<code>[<a href="http://www.weinman.com/wew/">Home</a>]</code>
<code>[<a href="http://www.cgibook.com/">CGI Book</a>]</code>
<code>[<a href="http://www.perlbook.com/">Perl Book</a>]</code>

</body>
</html>


  1. view.htmlp
  2. viewrec.htmlp
form.htmlp
<!-- $filename -->

<table>  <!-- for medicinal purposes -->

<tr> <td width=20 height=20>

<tr> <td width=20 height=20>
  <td width=300>

<form action="$callback" method=POST>

<h3>Please write in my Guestbook:</h3>

<p>Your Name:
<br><input type=text name=name value="$name" size=40>

<p>Where are you from?
<br><input type=text name=wherefor value="$wherefor" size=40>

<p>Say something cool:
<br>
<textarea cols=40 rows=10 name=message wrap=hard>$message</textarea>

<p>
<input type=submit value=" Make it so! ">
<input type=reset value=" Reset the form ">

<input type=hidden name=state value=validate>

</form>

</table>

header.htmlp
<!-- $filename -->
<html>
<title>$title</title>

<body link="#6666CC" vlink="#6666CC" alink="#CC6666">

<img src=guestbook.gif width=330 height=55>
<br clear=all>



initial.htmlp
<!-- $filename -->

<!-- the table is just here for aesthetic reasons 
     i use it to give the page some air 
  -->
<table>
  <tr><td width=20 height=30>
  <tr><td><td>

    <a href="$callback?state=create"><img src=create.gif width=115 height=45 
      border=0 alt="Create an entry"></a>

  <tr><td height=30>
  <tr><td><td>

    <a href="$callback?state=view"><img src=view.gif width=135 height=45 
      border=0 alt="View recent entries"></a>

  <tr><td height=30>
</table>


save.htmlp
<!-- $filename -->

<table>

  <tr><td height=35>
  <tr><td width=20><td width=300>

<h3>Your entry has been saved.</h3>

<form method=POST action="$callback">
<input type=hidden name=state value=view>

<input type=submit value=" Continue ">
</form>

  <tr><td height=35>

</table>




validate.htmlp
<!-- $filename -->

<h3>Here's your entry for the Guestbook:</h3>

$$viewrec.htmlp

<table>
  <tr><td width=20><td width=400><hr noshade size=3>
  <tr><td width=20><td width=400>

<form method=POST action="$callback">
<input type=hidden name=name value="$name">
<input type=hidden name=wherefor value="$wherefor">
<input type=hidden name=message value="$message">
<input type=hidden name=state value=save>

<p> If this entry looks good, <br>
<input type=submit value=" Save it. ">
</form>

<form method=POST action="$callback">
<input type=hidden name=name value="$name">
<input type=hidden name=wherefor value="$wherefor">
<input type=hidden name=message value="$message">
<input type=hidden name=state value=edit>

<p> If you need to change something, <br>
<input type=submit value=" Try again. ">
</form>

</table>

In this lesson, we will take a look at how the state-machine model makes it easy to implement multiple states in a CGI program.


Processing the state

Refering back to the guestbook program, the simplest example of an individual state is the "first" state:
sub first
{
htmlhead("My Guestbook!");
htmlp("initial.htmlp");
htmlfoot();
}

In fact, few of the states are any more complicated than this. That is the beauty of reusable code: when you break down a problem into its component pieces, each piece becomes simpler until it's manageable. The htmlhead and htmlfoot routines simply call htmlp for their respective files. That allows you to just edit the header.htmlp and footer.htmlp files whenever you feel like changing the look of the program.
The header.htmlp file has the common top part of all the HTML pages:
<!-- $filename -->
<html>
<title>$title</title>

<body >

<img src=guestbook.gif width=330 height=55>
<br clear=all> 

And the footer.htmlp file has the common bottom part of all the HTML pages:
<!-- $filename -->

<hr noshade size=1 width=300 align=left>
<small>
Based on the Magic Guestbook by
<a href="http://www.weinman.com/wew/">Bill</a>
<a href="http://www.weinman.com/">Weinman</a>
</small> <br>
<tt>[<a href="http://www.weinman.com/wew/">Home</a>]</tt>
<tt>[<a href="http://www.cgibook.com/">CGI Book</a>]</tt>
<tt>[<a href="http://www.perlbook.com/">Perl Book</a>]</tt>

</body>
</html>

The comment at the top of each file with the $filename variable is useful when you come back to the program sometime later and want to quickly see how all the files are put together. The htmlp() routine will replace that line with the actual name of the file. You can see from this that it's trivial to add more states when you need them. That makes it possible to create a program with as much or as little complexity as makes sense for the task at hand. The only state that's at all more complicated is the "view" state. The subroutine itself does not contain the complexity, though:
sub view
{
htmlhead("My Guestbook: $state");
htmlp("view.htmlp");
htmlfoot();
}

The loop for displaying all the individual guestbook entries happens logically in the middle of the htmlp file, so that's where it is:
<!-- $filename -->
<p> Go back to the <a href="$callback?state=first">
  Main Menu</a>

<p> Put in your own <a href="$callback?state=create">
  New Entry</a>

<h2>Recent Guestbook Entries</h2>
${ entries() }

<p> Go back to the <a href="$callback?state=first">
  Main Menu</a>

<p> Put in your own <a href="$callback?state=create">
  New Entry</a>

There, in the middle of the file is this line:
${ entries() }

That calls the entries() routine which fills in the HTML for all the guestbook entries. Without something like this, you would have to use a server-side include (SSI), if your server supports them. That SSI would then have to call a separate program which would read the database and insert the entries in the page. This is a much more complicated process that leaves you maintaining similar code in two separate Perl programs. In the next lesson, we will go through the process of installing the guestbook program on your server.

SEMrush Software