Perl CGI  «Prev  Next»

Lesson 5 Perl-based HTML
ObjectiveLearn how to use Perl-based HTML to make your state-machine CGI programs more manageable.

Perl-based HTML

From the last lesson, it is clear that your CGI program must generate all the HTML in order to maintain its state. Unfortunately, embedding all that HTML in your CGI program can quickly become unwieldy and unmanageable. One elegant solution is to use what I call Perl-based HTML.

Perl-based HTML

In a previous lesson (Module 2, Lesson 10, "Perl Substitute Operator"), you saw a small routine that makes it possible for a perl program to read an HTML file and expand perl variables inside the HTML. I have taken this concept another step to help with the state-management problem.

sub htmlp
{
local $filename = shift;
my $fhstring = $filename;
$fhstring =~ s/[^a-z]//i;

unless (-f $filename) {
  print qq(<h1>Error: </h1>\n );
  print qq(<p><em>htmlp</em> can't find "$filename"=/p>\n);
  return "";
  }  
open($fhstring, "<$filename");

while(<$fhstring>) {

  #  to execute perl code
  s/$\{(.*?)}/eval($1),""/eg;

  # $$filename to include another file
  s/$$([\S;]+;?)/htmlp($1)/eg;

  # $variable to include a variable
  s/$(\w+)//eg;

  print;
  } 

close $fhstring;
return "";
}

This version of the htmlp routine adds a couple of new features:
$variable   is still expanded to the contents of the variable
$$filename  includes another file by recursively calling htmlp
     executes arbitrary perl code from within the file

Using the $variable feature, it becomes trivial to rapidly deploy new states by calling htmlp with a file that has embedded Perl variables like this (I call these "htmlp" files):
<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>

Each of the variables in the htmlp file is defined in the Perl language CGI program. In this case:
$callback is the URL of the CGI program.
$name, $wherefor, and $message are the variables that carry the context of the form between calls.
An error routine can use this htmlp file:

<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>

Simply define the $error variable before calling htmlp("error.htmlp").
The $filename feature is convenient for creating one htmlp file that can be used repeatedly. This makes it much easier to present the user with a consistent interface, without having to code and recode the same screen several times, and then try to keep changes in sync.
The feature is the final piece that makes this more than just a convenience. This makes it possible to embed repetitive and conditional code inside the HTML. No, it does not run client-side, that is for languages like Java and JavaScript, but it does allow things like calling another routine for repetitive data or short conditional code for negotiating browser feature sets.
For those of you who are interested in how the regular expressions work in this code, click here for an explanation.

Perl Based html - Exercise

Click the Exercise link below to apply the htmlp() routine to the program from the previous lesson.
In the next lesson, you will work with a full example of a program that uses these features.
Perl Based HTML - Exercise