6.1 Embperl
Gerald Richter's Embperl
program is a popular solution for those who want to separate web page
design from data coding issues while taking advantage of
Perl's ability to generate dynamic content without
having to worry about web page design issues. As its name suggests,
Embperl provides the ability to embed Perl within your HTML
presentation layer templates.
The Embperl 2.0 release promises extensive
new capabilities, offering such features as XML and XSLT integration.
Although Embperl is implemented primarily in Perl, it also has a C
back end for speedier processing. For detailed information, go
to:
- http://perl.apache.org/embperl
- http://www.cpan.org/authors/id/GRICHTER
In the following sections we'll describe how to
install Embperl on Unix and Win32 systems. The Apache configuration
and execution of Embperl is virtually identical on the two systems,
so once we're installed on both systems
we'll run through a single configuration sequence.
6.1.1 Installing Embperl on Unix
This section describes how to install
Embperl and its associated modules on Unix platforms.
|
Although you can use Embperl under vanilla CGI Apache, we strongly
recommend that you use mod_perl. Not only is the
performance difference astonishing, but mod_perl
also allows you to use a wide range of Apache modules, including the
highly useful Apache::Session and
Apache::DBI. And without
Apache::Session (as we describe below), you will
get no session persistence between HTTP
requests.
|
|
If you're installing Embperl on Unix, you need to
obtain a few additional modules to get its full application benefit.
(Embperl is also expecting you to have pre-loaded
mod_perl, which provides it with many of its
extended options. We'll also assume this, for the
rest of this installation.)
- Storable.pm
-
Raphael Manfredi's popular
advanced module for storing various persistent data structures in
Perl (and required by Apache::Session). In the
later section, Section 6.1.5, we'll explain the
advantages of storing persistent web data. Download and install the
tarball from the following Perl 5 Porters
site:
http://www.cpan.org/authors/id/A/AM/AMS
- Apache::Session
-
Jeffrey Baker's Apache Perl module. This interface
between Apache and the Storable.pm module is
used to store persistent web data. Download and install it
from:
http://www.cpan.org/authors/id/JBAKER
- Apache::SessionX
-
This is a subsidiary module developed by Gerald Richter to complement
Embperl by creating an extended persistence framework for
Embperl's session data between HTTP requests (thus
extending Apache::Session). Download and install
the latest version from the CPAN site
at:
http://www.cpan.org/authors/id/GRICHTER
For
testing purposes, Embperl also requires that LWP and all of its
precursor modules be installed; Chapter 5,
contains the full details about LWP installation.
Once you've installed these required modules, you
can install Embperl itself. During the installation you need to
supply the location of your Apache source directory. Embperl can then
get hold of the relevant Apache code headers, and configure itself
against mod_perl. For example:
$ perl Makefile.PL
Build with support for Apache mod_perl?(y/n) [y]y
Use ../apache_1.3.24/src as Apache source(y/n) [y]y
...
Once Embperl has been configured, complete the installation as
follows:
$ make
$ make test
$ make install We can now head on down to Embperl's configuration.
6.1.2 Installing Embperl on Win32
Installing Embperl on Win32 is remarkably
easy because of the good work of those physics philosopher-kings at
the University of Winnipeg. The gig's all been tied
up with super-strings and made as simple as falling off a p-brane
bubble quark. When it's installing, take a look at
all of those modules you get. It's just like
Christmas:
PPM> set repository theoryx5
http://theoryx5.uwinnipeg.ca/cgi-bin/ppmserver.pl?urn:/PPMServer
PPM> set save
PPM> install Storable
Install package 'Storable?' (y/N): y
Installing package 'Storable'...
...
PPM> install Apache-Session
Install package 'Apache-Session?' (y/N): y
Installing package 'Apache-Session'...
...
PPM> install Apache-SessionX
Install package 'Apache-SessionX?' (y/N): y
Installing package 'Apache-SessionX'...
...
PPM> install Embperl
Install package 'Embperl?' (y/N): y
Installing package 'Embperl'...
...
PPM> quit
And that's it. We're now ready to
configure and deploy Embperl, a process that is virtually identical
on both Win32 and Unix.
6.1.3 Deploying HTML::Embperl
There are many different ways to deploy
Embperl, and all of them are discussed in depth within the
documentation. For starters, take a look at the information obtained
from the following command:
$ perldoc Embperl
Our favorite way of deploying Embperl is to ask the Apache web server
to call it. Apache can be called with any files bearing a particular
suffix (such as .epl) in the same way that you
can configure Apache to call Perl if it finds scripts ending with
.cgi. You do this in httpd.conf
by adding a handler (in our case a
PerlHandler) and associating a file type with a
nominated suffix in the following way. Here we have chosen the
typically generic Embperl .epl suffix:
PerlModule Embperl
EMBPERL_DEBUG 2285
<Files *.epl>
SetHandler perl-script
PerlHandler Embperl
Options ExecCGI
</files>
AddType text/html .epl
Once we restart Apache, every time anybody calls up a web page from
this server, suffixed with .epl, Embperl will be
called to deal with it.
There
are many different EMBPERL_DEBUG levels, and
we've chosen an output level initially recommended
by the Embperl download installation files. While
you're getting used to Embperl, you may want to try
these settings as a starting point, and then alter them to create
varying output within Apache's generated logs as you
progress.
We started, as illustrated in Example 6-1, with our
first Embperl .epl file, which checks up on who
is accessing which object within the Oracle database. A bit later
we'll run through how Embperl interprets this
information.
Example 6-1. ObjectAccess.epl — Embperl and Oracle
<html><head>
<title>Embperl Object Access Checker</title>
</head><body><center>
<h1>Hello Embperl, Let's Check Object Access! 8-)</h1><hr>
[-
$url = 'dbi:Oracle:orcl';
$user = 'system';
$passwd = 'manager';
use DBI ;
# Connect to the database
$dbh = DBI->connect($url, $user, $passwd, {RaiseError=>1});
# Prepare the SQL to check up on object access
$sth = $dbh->prepare ('select s.osuser "OS User", ' .
's.username "Username", ' .
's.serial# "Serial#", ' .
's.sid "Sid", ' .
'a.owner||\'.\'||a.object "Object Name", ' .
'\'=> \'||a.type "Lock Mode" ' .
'from v$session s, v$access a ' .
'where a.sid = s.sid ' .
'order by 6,1,2,3,4,5');
# Execute the Query
$sth->execute;
# Get the Column Headers
$head = $sth->{NAME} ;
# Fetch the data into the drillable data_ref array reference
$data_ref = $sth->fetchall_arrayref ;
-]
<table border="2">
<tr><th>[+ $head->[$col] +]</th></tr>
<tr><td>[+ $data_ref->[$row][$col] +]</td></tr>
</table>
<hr></center></body></html>
Store ObjectAccess.epl within the
../htdocs directory alongside ordinary flat HTML
files, and then fire up Apache. Our new Embperl file produced the
subsequent browser output in Figure 6-1. So
that's the culprit!
6.1.4 Looking at Embperl Syntax
Now
let's look at what is going on in Example 6-1. There are three main ways to actually embed
Perl within Embperl templates; these different approaches are
summarized in Table 6-1. In the following sections
we'll focus on how Embperl syntax differs from
standard Perl syntax.
Table 6-1. Embedding Perl within the Embperl template
[- ... -]
|
Code execution: The code between the
[- and the -] is executed,
without any HTML being generated. This approach is mainly for
assignments, function calls, creating database connections, and so
on, as in Example 6-1.
|
[-
$dbh = DBI->connect(
$url, $user, $passwd)
-]
|
[+ ... +]
|
Code output: The code is executed as
with the previous example, except this time the last thing evaluated
is streamed back to the HTML output.
|
<tr><th>
[+ $head->[$col] +]
</th></tr>
|
[! ... !]
|
One-time execution: The code is
executed as with [- ... -], but only for the
first request, which is useful for variable or subroutine
initialization and other one-off executions
|
[!
Sub session_start {
$start_time = localtime; }
!]
|
6.1.4.1 Controlling template-driven program flow
To exercise
structured program flow within Embperl, you can employ another
square-bracketed syntactical element:
- [$ <conditional element> <optional conditional construct> $]
This is perhaps best explained by working through the examples in the
following numbered list:
Suppose you want to set up a conditional if
chain to do different things with HTML. Depending upon how
you're being sent data, you do it like this:
[$ if $ENV{REQUEST_METHOD} eq 'GET' $]
<h2> I see you've called me with a GET request! :-) </h2>
[$ elsif $ENV{REQUEST_METHOD} eq 'POST' $]
<h2> Thanks for calling me with a POST request! 8-) </h2>
[$ else $]
<h1> You've created a new Request Method, Congratulations! $-) </h1>
[$ endif $] Notice that
although this code looks similar to ordinary Perl, brackets such as
(...), are missing from the main
if condition, and no curly brackets like
{...} are used to wrap statements. Also notice
that whereas in ordinary Perl you would use a left-facing bracket,
}, to end the complete if
statement, in Embperl you use endif instead.
This is a keyword that traditional Perl would fail to recognize.
|
We have been told that Embperl 2.0 will be more closely aligned with
standard Perl.
|
|
You can also use
while loops, for example, to display the Apache
server's current environment:
[$ while ($env_variable_name, $env_value) = each (%ENV) $]
[+ $env_variable_name +] = [+ $env_value +] <br>
[$ endwhile $] Again notice the use of endwhile rather than a
left-facing curly bracket, }.
Similarly, you can also employ do...until
loops:
[-
@crew = ('Kirk', 'McCoy', 'Spock', 'Beam Me Up');
$tribble = 0;
-]
[$ do $]
[+ $crew[ $tribble++ ] +]
[$ until $tribble > $#crew $] Notice how the tribbles keep growing in number.
You can also use foreach
loops:
[-
$warp_factor = 1;
@federation_planet = ('Earth', 'Vulcan',
'Solaria', 'Aurora', 'Terminus', 'Trantor');
-]
[$ foreach $thataway ( @federation_planet ) $]
Head for Federation Planet [+ $thataway +],
Mr Sulu, Warp Factor [+ $warp_factor++ +]
[$ endforeach $]
6.1.4.2 Strict variable naming
As with standard Perl, variables pop
into existence as soon as you mention them, but if
you'd rather enforce stricter discipline and
pre-declare global variable names, you can use
var:
[$ var $klingon @vulcan %romulan $]
This is equivalent to the Perl strict pragma
shown here:
use strict;
use vars qw ($klingon @vulcan %romulan) ;
6.1.4.3 Useful table tricks
The eagle-eyed among you may have spotted something strange about the
following lines in Example 6-1:
<tr><th>[+ $head->[$col] +]</th></tr>
<tr><td>[+ $data_ref->[$row][$col] +]</td></tr>
There is only one table header element, and one detail element, yet
the screen in Figure 6-1 is filled to overflowing
with the milk and honey of multiline and multicolumn results.
What's going on? A little bit of magic.
First, the special $col variable works out just
how many element are within the array referenced by
$head, which was created by the $head
= $sth->{NAME} code line. The special
$row variable does exactly the same for the
$data_ref reference value.
Next, Embperl iterates through the whole of the arrays accessed by
these variables, until $col and
$row return undef values
(i.e., they run out of milk and honey). You may want to avoid
questioning too much how Embperl does this; otherwise the fairy dust
may lose its sparkle. The Pandora's box of source
code is available though, if you're prepared to open
it.
6.1.5 Embperl Forms Handling and Apache::Session
One of the major benefits of the Web is
its stateless protocol, HTTP, which makes your processing extremely
lightweight at both the server and browser ends. Unfortunately, the
stateless protocol can also be a great disadvantage when compared
with a stateful client-server model, for example. The problem is that
you keep losing all of your user information every time users change
pages. This can be financially challenging if your site runs
shopping-cart applications!
Embperl can perform many of the regular
<hidden> type shenanigans to overcome this
limitation, but it can also make use of
Apache::Session to draw an Excalibur sword of
stateful data from a dry stone of statelessness. It stores this rich
vein of information between page requests via the following special
Perl hash
variables:
- %udat
-
Stores individual user data. Every time an individual comes back to
your server, via his browser, to hit different pages, you can access
all of his previously input data (if your Embperl script stored it
neatly away when you last had access to it).
- %mdat
-
Stores data for a nominated module or page.
- %fdat
-
Stores all of the data associated with a form.
- %idat
-
Stores all of the data input so far on a particular form, which is
very useful for those of us who relish sticky widgets.
|