Article

Embedding Perl Into Web Pages

Page: 1 2 3 4 5 6 7 8 9 10 11 Next

A Longer Example Revisited

As a more involved example of using HTML::Embperl, we illustrate the use of the telephone book lookup form. As before, the data is assumed to be in the file /usr/local/data/phone.txt, with one entry per line containing the name and phone number of a person, separated by the # symbol. We split this application across four files – a master file, phone.html, the query form, form.html, a lookup script, which gathers the data from the database, lookup.html, and a script to print out the results, print_it.html. In this example we also illustrate the use of cookies in saving session data across invocations of the script.

Within the <Location> directive specifying /embperl/object we also added:

  PerlSetEnv EMBPERL_OPTIONS 16

This directs Embperl not to pre-process the source for Perl expressions and is useful if we use a text editor for writing code. We should not set this if we use a WYSIWYG editor, which inserts unwanted HTML tags and escapes special characters automatically (for example, > to &gt;). See the HTML::Embperl documentation for further details on this and other options.

All files, using the previous Apache configuration, are to be placed in the directory specified by the /embperl/object location. The base file base.html is given by:

[- Execute 'header.html' -]          
<H3>Phone book example</H3>          
[- Execute ('*') -]          
[- Execute 'footer.html' -]

The header.html is:

[-        
   $title = 'My HTML::Embperl demo';        
-]          
<HTML>          
<HEAD><TITLE>[+ $title +]</TITLE></HEAD>        
<body bgcolor="#ffffff" link="#ff5599" vlink="#993399">          
<BR>

And, footer.html is:

<P>        
Comments to          
<A HREF="mailto:me@my.address.com">me</a>          
are welcome.          
</BODY>          
</HTML>

The master file by which the script is called, phone.html, consists of:

[$if ! $fdat{name} $]          
[-  Execute 'form.html' -]          
[$else$]          
[-        
   $http_headers_out{'Set-Cookie'} = "name=$fdat{name}";        
   Execute({inputfile => 'lookup.html', param => [$fdat{name}]});          
-]          
[$endif$]

We begin here by checking the special %fdat hash (containing the form data, which Embperl automatically supplies) for a value having been entered for the name parameter. If it hasn't, we print out the form contained in the include file form.html. If a value has been entered, we set a cookie via $http_headers_out{'Set-Cookie'}= "name=$fdat{name}" to save this value across sessions, and include a file lookup.html, which will query the database and print out the results. Note how we pass to this file the variable $name through the Execute({inputfile => 'lookup.html', param => [$fdat{name}]}) call. This example also illustrates how to set up if...else blocks within Embperl through the [$if$]...[$else$]...[$endif$] syntax (a similar syntax is available for while loops).

The file form.html used to print out the form by which the user enters the query is given by:

[- use CGI qw(cookie);        
   $val = cookie(-name => 'name');        
   -]        
   <FORM>        
   <TABLE><TR>        
   <TD>Please enter the name:</TD>        
   <TD>        
   <INPUT TYPE="text" NAME="name" SIZE=30 VALUE="[+$val+]">        
   </TD>            
   </TR><TR>            
   <TD COLSPAN=2>            
   <INPUT TYPE="submit" VALUE="Search!">        
   </TD></TR></TABLE>        
   </FORM>

This uses the cookie method of the CGI.pm module to retrieve the value of the cookie associated with the name parameter, if it is present. This value is used as the default for the textfield box in which the user enters the query.

When the user enters a value and submits the data, the file lookup.html will be called. This file is shown below:

[-        
   $name = $param[0];        
   open (PHONE, "/use/local/data/phone.txt")          
     or die "Cannot open phone.txt: $!";        
   while (<PHONE>) {        
      my @a = split /#/, $_;        
      next unless $a[0] =~ /$name/;        
      $match{$a[0]} = $a[1];        
   }          
close (PHONE);          
Execute({inputfile => "print_it.html", param => [\%match, $name]});          
-]

First it captures the $name variable passed to it in the master file via the @param array. It then opens up the database file and cycles through the entries, saving those entries that match the search criteria in the hash %match. After the results are obtained, the file is closed and a file print_it.html is included, which will print out the results (note that a reference to the %match hash containing the results and the original query term $name are passed to this file through the Execute call). The print_it.html file is as follows:

[-        
   $match = $param[0];        
   $name = $param[1];        
   @names = sort keys %$match;        
   @nums = map {$match->{$_}} @names;        
   $num = @names;          
-]          
[$if ($num > 0) $]          
[-        
   $string = sprintf(          
     "\\<B\\>%d\\</B\\> match%s for \\&quot;\\<B\\>%s\\</B\\        
      >\\&quot; %s found:",        
      $num, ($num > 1 ? 'es' : ''), $name, ($num == 1 ? 'was'        
      : 'were') );          
-]          
[+ $string +]        
   <HR>        
   <TABLE WIDTH="40%">        
   <TR><TH ALIGN="LEFT">Name</TH>        
   <TH ALIGN="LEFT">Number<TH></TR>        
   <TR>        
   <TD ALIGN="LEFT">[+ $names[$row] +]</TD>        
   <TD ALIGN="LEFT">[+ $nums[$row] +]</TD>        
   </TR>        
   </TABLE>        
   <HR>          
[$else$]        
   Sorry - nothing matched &quot;<B>[+ $name +]</B>&quot;.          
[$endif$]          
[- use CGI qw(url);        
   $url = url;          
-]        
   Try <A HREF="[+ $url +]">another search</A>.

In this file we first capture the variables passed into it from lookup.html via the @param array. For later use we construct two arrays, @names and @nums, from the passed %match hash reference. These arrays contain respectively, the names and the numbers of the successful matches. We also set a variable $num equal to the number of successful matches obtained. If there were any, we print out the results in a table, using the automatic row generation feature of Embperl and through the use of the $row global variable. If there were no matches, we report that as such. Finally, at the bottom of this page we provide a link back to the original script through the url function of the CGI.pm module.

One aspect of Embperl illustrated in this example is that when printing out raw HTML tags present in some variable $string through the [+ $string +] syntax, the tags themselves must be escaped. This is done explicitly in this example, although Embperl has the capability to do this automatically when certain options are set.

Screenshots of this application in action, which would be called as http://localhost/embperl/object/phone.html are similar to those of the corresponding Mason example, so will not be repeated here.

As was done with Mason, these examples are meant just to show the basic structure of Embperl. For more complex examples, again including some on interacting with databases and on handling form data and sessions (which requires the Apache::Session module), we refer to the web site at http://perl.apache.org/embperl/ and also to the examples contained within the source distribution. Also, if a lot of work is to be done with databases, we may want to look at the DBIx::RecordSet module, which gives a common interface to querying databases of various types, which is particularly suitable in a web environment. DBIx::RecordSet is written by the same author as Embperl and so the two modules work very nicely together.

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