O'Reilly logo

Embedding Perl in HTML with Mason by Ken Williams, Dave Rolsky

Stay ahead with the world's most comprehensive technology and business learning platform.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

Start Free Trial

No credit card required

Alternatives to Mason

Much of this chapter so far may have sounded like a sales pitch, because we wanted you to know about Mason’s biggest strengths so you could have some solid reasons for reading the rest of this book. However, you should also be aware that there are many alternatives to using Mason, and an awareness of these alternatives will help you form an accurate picture of the context for which each system was created. It will also help you decide which system to use for each individual project, because no single system was designed to be a solution to all the problems you might encounter. Just as importantly, different people find that different systems suit the way they think better than others do.

There are generally two kinds of systems that people consider to be alternatives to Mason: lightweight solutions and heavyweight solutions. Lightweight solutions generally have the goal of being small and fast and leave much of the major work up to you. They are often simple templating modules like Text::Template or HTML::Template or even homegrown templating schemes. Using templates is certainly a good idea, and it is one of the core ideas in Mason itself. However, when designing an entire site, you’re usually going to need some more sophisticated system that helps you manage your site-building resources; if you choose a templating-only solution, you’ll probably end up writing this management code yourself. You may have a good idea of what such a system would entail only after writing and maintaining dozens of complicated web sites, so you’d likely spend more time working on your management code than on building your sites. This is the main trade-off with lightweight solutions: you gain flexibility because you can manage your site however you want, but since the burden rests entirely on you, you might end up preferring to use a tool that handles many of these management issues for you.

By contrast, heavyweight solutions implement several layers on top of their templating capabilities. Despite some disagreement on proper use of the term, “application server” is often used to describe such heavyweight systems. Each anticipates the typical needs of a large, sophisticated web site and provides methods for dealing with these situations cleanly. A heavyweight system will typically have support for integrating a site with a database, working with HTML and URLs, preserving state from one request to the next, caching often-used resources, and dealing with error conditions. Each heavyweight solution is tailored to different site requirements and makes different assumptions about the best ways to deal with them.

Good solutions, such as Mason, Embperl, and Apache::ASP, also help you organize your site code in a way that lets you think about your site’s structure in an organized way, both on the small scale and the large scale. They help you design a site that is easy to build and easy to maintain.

Mason itself is sort of a unique offering. It sits somewhere in the middle between lightweight and heavyweight solutions, though it leans a bit toward the heavy. It doesn’t directly provide support for database connections, HTML munging, or sessions, but it makes it so easy for you to use regular Perl tools for these purposes that you’ll never miss the functionality. If you do decide that Mason is missing a feature you really need, it’s easy to add functionalities to Mason and use them just as if they were built in. In a sense, Mason’s main strengths lie in the ways it lets you interface various parts of your site with one another and with outside resources.

Consider these design goals as you read the following descriptions. When possible, we have worked with the authors of these systems to make sure the descriptions highlight each system’s best features. Keep in mind, though, that our list of alternatives is by no means exhaustive. There are countless other solutions. We have tried to pick the most popular solutions, but for more information on any product you might want to use, read its documentation, find an appropriate mailing list in which to ask questions, and make your own decision.

Embperl

Of the systems presented in this chapter, Embperl may be the most similar one to Mason. Embperl is one of the oldest heavyweight systems that is still in widespread use. It has been used for several years under the name HTML::Embperl , but recent beta releases have switched the module name to just Embperl. Its author, Gerald Richter, is generally very responsive to bug reports and feature requests.

Embperl is targeted specifically toward generating HTML and has several “magical” HTML-manipulation features. For instance, HTML tables can be autogenerated by using the special Embperl variables $row , $col , and $cnt :

[- @k = qw(zero one two) -]
<table>
 <tr>
  <td>[+ $row     +]</td>
  <td>[+ $k[$row] +]</td>
 </tr>
</table>

This would output:

<table>
 <tr>
  <td>0</td>
  <td>zero</td>
 </tr>
 <tr>
  <td>1</td>
  <td>one</td>
 </tr>
 <tr>
  <td>2</td>
  <td>two</td>
 </tr>
</table>

This means that Embperl does some scanning of your HTML and your Perl code to decide when you mean to use its magical generation. Some people find this assistance useful, and others would prefer to manage the generation themselves (the approach that Mason takes). The equivalent Mason code would require an explicit loop:

% my @k = qw(zero one two);
<table>
% foreach my $row (0..$#k) {
 <tr>
  <td><% $row     %></td>
  <td><% $k[$row] %></td>
 </tr>
% }
</table>

Notice that the Embperl delimiters for embedded Perl code are based on square brackets like [+ +]. This is so that Embperl code can be written by using a WYSIWYG HTML editor that might get confused by angle brackets and treat them as HTML code. Embperl takes this even further and lets you write Perl code that is HTML-escaped by the editor, like so:

[- $i = 0; -]
[$ while ($i &lt; 5) $]
  Row: [+ $i++ +]<br>
[$ endwhile $]

The text &lt; will be converted to < by Embperl before execution.

Notice also that Embperl uses its own custom loop control syntax rather than Perl’s built-in loop control. There is experimental support in Version 1.2b2 and higher for using native Perl loops, and it will be part of the stable feature set in Embperl Version 2.

Embperl has a feature called EmbperlObjects, which is an inheritance system similar to Mason’s autohandler functionality. It also offers integrated support for preserving state between requests with Apache::Session via another special variable, %udat. This can be very handy; see Chapter 12 for how you can accomplish a similar effect with Mason.

Variables you create in Embperl are usually dynamically scoped as either local or global variables (not lexical my( ) variables), which can sometimes be a bit unnerving in a persistent environment like mod_perl. Fortunately, after each request, Embperl will clean up any variables you created during the request. Variables declared with local( ) or my( ) in Embperl are usually scoped to the substitution tag enclosing them. Contrast this to Mason, in which the default scope of localized variables is the entire component. Because of this, it is more common to see my( ) in Mason code and global variables in Embperl code.

Embperl Version 1.x also provides some support for using the Safe.pm module, which can provide some protection against executing malicious Perl code. This strategy is somewhat dubious, however, because the Safe module is fairly easily defeated and because we hope your page designers aren’t going to be trying to sabotage your servers in the first place. Moreover, when using Safe mode, you won’t be able to access outside resources like databases, so it might not even be an option in the first place. Because of these problems, support for Safe mode has been removed in Embperl Version 2.

Embperl 2 will add several new features, including support for XML/XSLT processing, custom template syntax, and a highly customizable data caching and output filtering system.

Apache::ASP

Apache::ASP , by Joshua Chamas, is a package for writing Active Server Pages under mod_perl. It is fairly mature (its initial release was in 1998), and several years of development and active use by the Perl community have created a feature set that includes several useful extensions to the Microsoft standard.

With Apache::ASP, instead of using VBScript or JScript for the dynamic portions of the pages, you use Perl.[2] The ASP feature set has been neatly translated to Perl, so you have access to all of ASP’s built-in features such as session management (using a custom session manager, not Apache::Session), email integration, and the ASP object model.

The Perl embedding syntax is very simple: <% %> tags get wrapped around Perl control structures or miscellaneous Perl instructions, and <%= %> tags are wrapped around Perl expressions whose values you wish to insert into the surrounding HTML. For example:

<h2>Font sizes:</h2>
<% foreach my $i (1..5) { %>
  <font size="<%= $i %>">Size = <%= $i %></font><br>
<% } %>

The Mason equivalent is very similar:

<h2>Font sizes:</h2>
% foreach my $i (1..5) {
  <font size="<% $i %>">Size = <% $i %></font><br>
% }

The output of both examples is:

<h2>Font sizes:</h2>
  <font size="1">Size = 1</font><br>
  <font size="2">Size = 2</font><br>
  <font size="3">Size = 3</font><br>
  <font size="4">Size = 4</font><br>
  <font size="5">Size = 5</font><br>

Because it is built on the ASP model, Apache::ASP is a natural choice when porting an ASP/IIS application to the Apache platform. You will need to translate the scripting language from VBScript or JScript into Perl, but the overall structure of the site should remain unchanged.

Besides the standard ASP feature set, Apache::ASP supports several additional features, including extra event handlers, XML/XSLT processing, and component output caching. It also supports a cookieless mode for maintaining session data, which can be very handy for end users unwilling or unable to store session cookies. The XSLT support is particularly interesting, since combining it with the output caching features means that you can use dynamic XSLT transformations in web publishing, a technique that might be computationally prohibitive without caching.

For more information on Apache::ASP, please visit http://www.apache-asp.org/.

HTML::Template

Sam Tregar’s HTML::Template module falls into the lightweight category. Its chief goal is to allow site builders to separate a site’s HTML from its Perl controlling code, and it enforces this division quite strictly. No Perl code is ever embedded within templates, and control structures like if, include, and various loops are all implemented by custom HTML::Template tags. Any variables to be interpolated into the HTML template are explicitly fed to the template by the controlling Perl code.

Philosophically, the reason for this strict division of HTML and Perl is so that a division of labor can be enforced in an organization, with HTML designers and Perl coders working independently, not worrying about whether they’re editing the same files. It is also possible to apply the same controlling code to several different templates, so that designers can create different look-and-feel templates without involving programmers.

HTML::Template is generally very fast at filling in HTML templates, especially if you use its just-in-time compiler HTML::Template::JIT. It also provides a caching mechanism, somewhat similar to Mason’s, that allows for caching templates in private memory, on disk, in memory shared between processes, or in combinations thereof. Unlike Mason, HTML::Template’s caching handles the caching only of templates themselves, not of their output or arbitrary data.

Example syntax:

<h1>Employee listing:</h1>
<TMPL_LOOP NAME=EMPLOYEE_INFO>
  Name: <TMPL_VAR NAME=NAME> <br>
   Job: <TMPL_VAR NAME=JOB> <br>
</TMPL_LOOP>

To make this actually do something, you need to write Perl code to call the template. For this template, we might write something like this:

my $template = HTML::Template->new( filename => 'emp_list.tmpl' );
$template->param( EMPLOYEE_INFO =>
                  [ { NAME => 'Dave', JOB => 'Grouper of Bumpers' },
                    { NAME => 'Ken',  JOB =>  'Bumper of Groupers'} ] );
print "Content-Type: text/html\n\n";
print $template->output;

Note that the top layer for the system is a Perl script. Some people love this, some people hate it. You may know by now which category you fall into.

Text::Template

Text::Template , written by Mark-Jason Dominus, is a lightweight solution similar to HTML::Template, but has some philosophical differences. First, it does not assume that the template contains HTML but is designed to work with any kind of text in the template (in truth, HTML::Template can work with arbitrary text, too, but it was designed specifically to work with HTML). Second, it uses native Perl control structures instead of its own custom macros, so Perl programmers have less to keep in their heads. This has the effect of breaking down the barrier that HTML::Template maintains between code and HTML, so in an environment in which designers and programmers need exclusive control over their own work products, HTML::Template may be the better choice.

Like Embperl, Text::Template also supports code sequestering via the Safe.pm module, with the same caveats as mentioned earlier. Template variables can be passed explicitly to the template for substitution or drawn from Perl variables in a specified Perl package. Text::Template also allows the user to customize what delimiters are used to indicate the special Perl code or variable substitution sections. The default delimiters are curly braces:

my $string = q[
  Dear {$recipient},
   Congratulations!  You have won {$amount} dollar{$plural}!
];
my $template = Text::Template->new(TYPE => 'STRING', SOURCE => $string );
$T::recipient = int(rand 2) ? 'Mary' : 'John';
$T::amount    = int(rand 10) - 5;
$T::plural    = $T::amount == 1 ? '' : 's';

print $template->fill_in(PACKAGE => 'T');

Text::Template was first released in 1995 and has undergone many revisions in its life cycle. It is considered a mature product, and its author is very responsive to comments and questions about it. There is also a low-volume mailing list for users of Text::Template, the details of which can be found in the module documentation.

Template Toolkit

In order to combat the proliferation of zillions of templating modules that all look and act similar but contain maddening and meaningless differences, the Template Toolkit package by Andy Wardley aims to be the only templating package you’ll ever need and offers an extremely full-featured templating system. Like HTML::Template, it uses a large set of custom control macro tags like IF , SWITCH, FOREACH, FILTER, and so on, as well as more advanced tags like FILTER , TRY and CATCH, and MACRO. It can either allow embedded Perl as Text::Template does or disallow it as HTML::Template does. Like Mason, it lets you build a site in terms of modular components. There is also an Apache::Template module that facilitates building a mod_perl-based site out of Template Toolkit components.

An example of Template Toolkit usage follows:

my $string = q(
  Dear [% recipient %],
   Congratulations!  You have won [% amount %] dollar[% plural %]!
);

my $template = new Template;
my %vars = (recipient => (int(rand 2) ? 'Mary' : 'John'),
            amount    => int(rand 10) - 5);
$vars{plural} = $vars{amount} == 1 ? '' : 's';

$template->process(\$string, \%vars);

Because of its many features and its well-supported development, the Template Toolkit is becoming the modern standard for standalone templates. It is quite different in philosophy from Mason, though, so we do not consider it to be in direct competition as a tool for the same situations we’d use Mason for.

PHP

PHP (http://www.php.net/) is pretty far removed from Mason, but we mention it here because of its popularity. PHP is another mechanism for embedding functionality into web pages, but PHP does not use Perl as its scripting language. The name PHP can refer variously to the embedding system itself, the scripting language, or the interpreter that renders the HTML pages.

It is important to understand some of the properties of PHP before deciding to use it. One of the design goals of PHP is to be as simple as possible to install and start using, and in some cases this means that features that experienced Perl programmers rely on are not present. For instance, PHP lacks support for private namespaces, there is no way to create three-tiered applications that separate business logic and presentation code, and there is no mechanism for creating reusable code modules. The Apache mod_php module is only a content generation module, so it cannot cooperate with other request phases in the same way Mason can cooperate with mod_perl’s authentication or filename translation phases.[3]

Importantly, although there is a lot of user-contributed code in the PHP world, it cannot match the breadth and depth of Perl’s CPAN. It has often been said that the CPAN is Perl’s “killer app,” and programmers most appreciate the CPAN when they least expect it.

Finally, although you can theoretically use PHP for general-purpose programming, it wasn’t designed for that. PHP is typically used only for embedding PHP code into templates, whereas Perl is a full-featured programming language used for more purposes than any single programmer could imagine. While this does make PHP well-suited for the common tasks of web scripting, it may be limiting. For instance, a certain Perl programming friend was recently contracted to write a “simple shopping cart system” that had one small addition: it had to do some horribly complex optics calculations. For situations like these, a general-purpose programming language like Perl can be quite handy.



[2] A third-party PerlScript option is also available, but it is not as widely used as VBScript or JScript.

[3] Although Mason is also just a content generation module, it cooperates with the other request phases by virtue of mod_perl’s support for sharing information among the request phases.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, interactive tutorials, and more.

Start Free Trial

No credit card required