WEB(3)

NAME

Template::Tutorial::Web - Generating Web Content Using the
Template Toolkit

DESCRIPTION

This tutorial document provides a introduction to the Tem
plate Toolkit and demonstrates some of the typical ways it
may be used for generating web content. It covers the
generation of static pages from templates using the tpage
and ttree scripts and then goes on to show dynamic content
generation using CGI scripts and Apache/mod_perl handlers.

Various features of the Template Toolkit are introduced
and described briefly and explained by use of example.
For further information, see Template, Template::Manual
and the various sections within it. e.g.
perldoc Template # Template.pm mod
ule usage
perldoc Template::Manual # index to manual
perldoc Template::Manual::Config # e.g. configura
tion options
The documentation is now also distributed in HTML format
(or rather, in the form of HTML templates). See the
'docs' sub-directory of the distribution for further
information on building the HTML documentation.
If you're already reading this as part of the HTML docu
mentation, then you don't need to worry about all that.
You can have a seat, sit back.
back and enjoy the rest of the tutorial...

INTRODUCTION

The Template Toolkit is a set of Perl modules which col
lectively implement a template processing system. In this
context, a template is a text document containing special
markup tags called 'directives'. A directive is an
instruction for the template processor to perform some
action and substitute the result into the document in
place of the original directive. Directives include those
to define or insert a variable value, iterate through a
list of values (FOREACH), declare a conditional block
(IF/UNLESS/ELSE), include and process another template
file (INCLUDE) and so on.

In all other respects, the document is a plain text file
and may contain any other content (e.g. HTML, XML, RTF,
LaTeX, etc). Directives are inserted in the document
within the special markup tags which are '[%' and '%]' by
default, but can be changed via the module configuration
options. Here's an example of an HTML document with addi
tional Template Toolkit directives.
[% INCLUDE header
title = 'This is an HTML example'
%]
<h1>Some Interesting Links</h1>
[% webpages = [
{ url => 'http://foo.org', title => 'The Foo Or
gansiation' }
{ url => 'http://bar.org', title => 'The Bar Or
gansiation' }
]
%]
Links:
<ul>
[% FOREACH link = webpages %]
<li><a href="[% link.url %]">[% link.title %]</a>
[% END %]
</ul>
[% INCLUDE footer %]
This example shows how the INCLUDE directive is used to
load and process separate 'header' and 'footer' template
files, including the output in the current document.
These files might look like this:
header:

<html>
<head>
<title>[% title %]</title>
</head>
<body bgcolor="#ffffff">
footer:

<hr>
<center>
&copy; Copyright 2000 Me, Myself, I
</center>
</body>
</html>
The example also uses the FOREACH directive to iterate
through the 'webpages' list to build a table of links. In
this example, we have defined this list within the tem
plate to contain a number of hash references, each con
taining a 'url' and 'title' member. The FOREACH directive
iterates through the list, aliasing 'link' to each item
(hash ref). The [% link.url %] and [% link.title %] directives then access the individual values in the hash
and insert them into the document.
The following sections show other ways in which data can
be defined for use in a template.

GENERATING STATIC PAGES

Having created a template file we can now process it to
generate some real output. The quickest and easiest way
to do this is to use the tpage script. This is provided
as part of the Template Toolkit and should be installed in
your usual Perl bin directory.

Assuming you saved your template file as 'mypage.html',
you would run the command:
tpage mypage.html
This will process the template file, sending the output to
STDOUT (i.e. whizzing past you on the screen). You may
want to redirect the output to a file but be careful not
to specify the same name as the template file, or you'll
overwrite it. You may want to use one prefix for your
templates such as '.atml' (for 'Another Template Markup
Language', perhaps?) and the regular '.html' for the out
put files (assuming you're creating HTML, that is).
Alternatively, you might redirect the output to another
directory. e.g.

tpage mypage.atml > mypage.html
tpage templates/mypage.html > html/mypage.html
The tpage script is very basic and only really intended to
give you an easy way to process a template without having
to write any Perl code. A much more flexible tool is
ttree, described below, but for now let's look at the out
put generated by processing the above example (some
whitespace removed for brevity):

<html>
<head>
<title>This is an HTML example</title>
</head>
<body bgcolor="#ffffff">
<h1>Some Interesting Links</h1>
Links:
<ul>
<li><a href="http://foo.org">The Foo Organsia
tion</a>
<li><a href="http://bar.org">The Bar Organsia
tion</a>
</ul>
<hr>
<center>
&copy; Copyright 2000 Me, Myself, I
</center>
</body>
</html>
The header and footer template files have been included (assuming you created them and they're in the current
directory) and the link data has been built into an HTML
list.
The ttree script, also distributed as part of the Template
Toolkit, provides a more flexible way to process template
documents. The first time you run the script, it will ask
you if it should create a configuration file, usually
called '.ttreerc' in your home directory. Answer 'y' to
have it create the file.
The ttree documentation describes how you can change the
location of this file and also explains the syntax and
meaning of the various options in the file. Comments are
written to the sample configuration file which should also
help.

perldoc ttree
ttree -h
In brief, the configuration file describes the directories
in which template files are to be found (src), where the
corresponding output should be written to (dest), and any
other directories (lib) that may contain template files
that you plan to INCLUDE into your source documents. You
can also specify processing options (such as 'verbose' and
'recurse') and provide regular expression to match files
that you don't want to process (ignore, accept) or should
be copied instead of processed (copy).
An example .ttreerc file is shown here:
$HOME/.ttreerc:
verbose
recurse
# this is where I keep other ttree config files
cfg = ~/.ttree
src = ~/Cebsrc/src
lib = ~/Vebsrc/lib
dest = ~/Sublic_html/test
ignore = R
C
You can create many different configuration files and
store them in)the directory specified in the 'cfg' option,
shown above. You then add the "-f filename" option to
ttree to have it read that file.
When you run the script, it compares all the files in the
'src' directory (including those in sub-directories if the
'recurse' option is set), with those in the 'dest' direc
tory. If the destination file doesn't exist or has an
earlier modification time than the corresponding source
file, then the source will be processed with the output
written to the destination file. The "-a" option forces
all files to be processed, regardless of modification
times.
The script doesn't process any of the files in the 'lib' directory, but it does add it to the INCLUDE_PATH for the
template processor so that it can locate these files via
an INCLUDE or PROCESS directive. Thus, the 'lib' direc
tory is an excellent place to keep template elements such
as header, footers, etc., that aren't complete documents
in their own right.
You can also specify various Template Toolkit options from
the configuration file. Consult the ttree documentation
and help summary ("ttree -h") for full details. e.g.
$HOME/.ttreerc:
pre_process = config
interpolate
post_chomp
The 'pre_process' option allows you to specify a template
file which should be processed before each file. Unsur
prisingly, there's also a 'post_process' option to add a
template after each file. In the fragment above, we have
specified that the 'config' template should be used as a
prefix template. We can create this file in the 'lib'
directory and use it to define some common variables,
including those web page links we defined earlier and
might want to re-use in other templates. We could also
include an HTML header, title, or menu bar in this file
which would then be prepended to each and every template
file, but for now we'll keep all that in a separate
'header' file.
$lib/config:

[% root = '~/abw'
home = "$root/index.html"
images = "$root/images"
email = 'abw@kfs.org'
graphics = 1
webpages = [
{ url => 'http://foo.org', title => 'The Foo Or
gansiation' }
{ url => 'http://bar.org', title => 'The Bar Or
gansiation' }
]
%]
Assuming you've created or copied the 'header' and
'footer' files from the earlier example into your 'lib'
directory, you can now start to create web pages like the
following in your 'src' directory and process them with
ttree.
$src/newpage.html:

[% INCLUDE header
title = 'Another Template Toolkit Test Page'
%]
<a href="[% home %]">Home</a>
<a href="mailto:[% email %]">Email</a>
[% IF graphics %]
<img src="[% images %]/logo.gif" align=right width=60
height=40>
[% END %]
[% INCLUDE footer %]
Here we've shown how pre-defined variables can be used as
flags to enable certain feature (e.g. 'graphics') and to
specify common items such as an email address and URL's
for the home page, images directory and so on. This
approach allows you to define these values once so that
they're consistent across all pages and can easily be
changed to new values.
When you run ttree, you should see output similar to the
following (assuming you have the verbose flag set).

ttree 1.14 (Template Toolkit version 1.02a)
C
Source: /hVme/abw/websrc/src
Destination: /hSme/abw/public_html/test
Include Path: [ |home/abw/websrc/lib ]
Ignore: [ R
Copy: [ C]
Accept: [ * ]
)
+ newpage.html
The '+' before 'newpage.html' shows that the file was pro
cessed, with the output being written to the destination
directory. If you run the same command again, you'll see
the following line displayed instead showing a '-' and
giving a reason why the file wasn't processed.

- newpage.html (not modified)
It has detected a 'newpage.html' in the destination direc
tory which is more recent than that in the source direc
tory and so hasn't bothered to waste time re-processing
it. To force all files to be processed, use the "-a"
option. You can also specify one or more filenames as
command line arguments to ttree:

tpage newpage.html
This is what the destination page looks like.
$dest/newpage.html:

<html>
<head>
<title>Another Template Toolkit Test Page</title>
</head>
<body bgcolor="#ffffff">
<a href="~/abw/index.html">Home</a>
<a href="mailto:abw@kfs.org">Email me</a>
<img src="~/abw/images/logo.gif" align=right width=60
height=40>
<hr>
<center>
&copy; Copyright 2000 Me, Myself, I
</center>
</body>
</html>
You can add as many documents as you like to the 'src'
directory and ttree will apply the same process to them
all. In this way, it is possible to build an entire tree
of static content for a web site with a single command.
The added benefit is that you can be assured of consis
tency in links, header style, or whatever else you choose
to implement in terms of common templates elements or
variables.

DYNAMIC CONTENT GENERATION VIA CGI SCRIPT

The Template module provides a simple front-end to the
Template Toolkit for use in CGI scripts and
Apache/mod_perl handlers. Simply 'use' the Template mod
ule, create an object instance with the new() method and
then call the process() method on the object, passing the name of the template file as a parameter. The second
parameter passed is a reference to a hash array of vari
ables that we want made available to the template:
#!/usr/bin/perl -w
use strict;
use Template;
my $file = 'src/greeting.html';
my $vars = {
message => "Hello World0
};
my $template = Template->new();
$template->process($file, $vars)
|| die "Template process failed: ", $template->er
ror(), "0;
So that our scripts will work with the same template files
as our earlier examples, we'll can add some configuration
options to the constructor to tell it about our environ
ment:

my $template->new({
# where to find template files
INCLUDE_PATH => '/home/abw/web
src/src:/home/abw/websrc/lib',
# pre-process lib/config to define any extra val
ues
PRE_PROCESS => 'config',
});
Note that here we specify the 'config' file as a PRE_PRO
CESS option. This means that the templates we process can
use the same global variables defined earlier for our
static pages. We don't have to replicate their defini
tions in this script. However, we can supply additional
data and functionality specific to this script via the
hash of variables that we pass to the process() method.
These entries in this hash may contain simple text or
other values, references to lists, others hashes, sub-rou
tines or objects. The Template Toolkit will automatically
apply the correct procedure to access these different
types when you use the variables in a template.
Here's a more detailed example to look over. Amongst the
different template variables we define in $vars, we create
a reference to a CGI object and a 'get_user_projects'
sub-routine.

#!/usr/bin/perl -w
use strict;
use Template;
use CGI;
$| = 1;
print "Content-type: text/html0;
my $file = 'userinfo.html';
my $vars = {
'version' => 3.14,
'days' => [ qw( mon tue wed thu fri sat sun )
],
'worklist' => get_user_projects,
'cgi' => CGI->new(),
'me' => {
'id' => 'abw',
'name' => 'Andy Wardley',
},
};
sub get_user_projects {
my $user = shift;
my @projects = ... # do something to retrieve
data
return @projects;
}
my $template = Template->new({
INCLUDE_PATH => '/home/abw/web
src/src:/home/abw/websrc/lib',
PRE_PROCESS => 'config',
});
$template->process($file, $vars)
|| die $template->error();
Here's a sample template file that we might create to
build the output for this script.
$src/userinfo.html:

[% INCLUDE header
title = 'Template Toolkit CGI Test'
%]
<a href="mailto:[% email %]">Email [% me.name %]</a>
<p>This is version [% version %]</p>
<h3>Projects</h3>
<ul>
[% FOREACH project = worklist(me.id) %]
<li> <a href="[% project.url %]">[% project.name
%]</a>
[% END %]
</ul>
[% INCLUDE footer %]
This example shows how we've separated the Perl implemen
tation (code) from the presentation (HTML) which not only
makes them easier to maintain in isolation, but also
allows the re-use of existing template elements such as
headers and footers, etc. By using template to create the
output of your CGI scripts, you can give them the same
consistency as your static pages built via ttree or other
means.
Furthermore, we can modify our script so that it processes
any one of a number of different templates based on some
condition. A CGI script to maintain a user database, for
example, might process one template to provide an empty
form for new users, the same form with some default values
set for updating an existing user record, a third template
for listing all users in the system, and so on. You can
use any Perl functionality you care to write to implement
the logic of your application and then choose one or other
template to generate the desired output for the applica
tion state.

DYNAMIC CONTENT GENERATION VIA APACHE/MOD_PERL HANDLER

NOTE: the Apache::Template module is now available from
CPAN and provides a simple and easy to use Apache/mod_perl
interface to the Template Toolkit. It's only in it's
first release (0.01) at the time of writing and it cur
rently only offers a fairly basic facility, but it imple
ments most, if not all of what is described below, and it
avoids the need to write your own handler. However, in
many cases, you'll want to write your own handler to cus
tomise processing for your own need, and this section will
show you how to get started.

The Template module can be used in a similar way from an
Apache/mod_perl handler. Here's an example of a typical
Apache httpd.conf file:
PerlModule CGI;
PerlModule Template
PerlModule MyOrg::Apache::User
PerlSetVar websrc_root /home/abw/websrc
<Location /user/bin>
SetHandler perl-script
PerlHandler MyOrg::Apache::User
</Location>
This defines a location called '/user/bin' to which all
requests will be forwarded to the handler() method of the MyOrg::Apache::User module. That module might look some
thing like this:

package MyOrg::Apache::User;
use strict;
use vars qw( $VERSION );
use Apache::Constants qw( :common );
use Template qw( :template );
use CGI;
$VERSION = 1.59;
sub handler {
my $r = shift;
my $websrc = $r->dir_config('websrc_root')
or return fail($r, SERVER_ERROR,
"'websrc_root' not specified");
my $template = Template->new({
INCLUDE_PATH => "$websrc/src/user:$web
src/lib",
PRE_PROCESS => 'config',
OUTPUT => $r, # direct output to
Apache request
});
my $params = {
uri => $r->uri,
cgi => CGI->new,
};
# use the path_info to determine which template
file to process
my $file = $r->path_info;
$file =~ s[^/][];
$r->content_type('text/html');
$r->send_http_header;
$template->process($file, $params)
|| return fail($r, SERVER_ERROR, $tem
plate->error());
return OK;
}
sub fail {
my ($r, $status, $message) = @_;
$r->log_reason($message, $r->filename);
return $status;
}
The handler accepts the request and uses it to determine
the 'websrc_root' value from the config file. This is
then used to define an INCLUDE_PATH for a new Template
object. The URI is extracted from the request and a CGI
object is created. These are both defined as template
variables.
The name of the template file itself is taken from the
PATH_INFO element of the request. In this case, it would
comprise the part of the URL coming after '/user/bin',
e.g for '/user/bin/edit', the template file would be
'edit' located in "$websrc/src/user". The headers are
sent and the template file is processed. All output is
sent directly to the print() method of the Apache request object.

USING PLUGINS TO EXTEND FUNCTIONALITY

As we've already shown, it is possible to bind Perl data
and functions to template variables when creating dynamic
content via a CGI script or Apache/mod_perl process. The
Template Toolkit also supports a plugin interface which
allows you define such additional data and/or functional
ity in a separate module and then load and use it as
required with the USE directive.

The main benefit to this approach is that you can load the
extension into any template document, even those that are
processed "statically" by tpage or ttree. You don't need to write a Perl wrapper to explicitly load the module and
make it available via the stash.

Let's demonstrate this principle using the DBI plugin
written by Simon Matthews <sam@knowledgepool.com>. You
can create this template in your 'src' directory and pro
cess it using ttree to see the results. Of course, this
example relies on the existence of the appropriate SQL
database but you should be able to adapt it to your own
resources, or at least use it as a demonstrative example
of what's possible.
[% INCLUDE header
title = 'User Info'
%]
[% USE DBI('dbi:mSQL:mydbname') %]
<table border=0 width="100%">
<tr>
<th>User ID</th>
<th>Name</th>
<th>Email</th>
</tr>
[% FOREACH user = DBI.query('SELECT * FROM user ORDER
BY id') %]
<tr>
<td>[% user.id %]</td>
<td>[% user.name %]</td>
<td>[% user.email %]</td>
</tr>
[% END %]
</table>
[% INCLUDE footer %]
A plugin is simply a Perl module in a known location and
conforming to a known standard such that the Template
Toolkit can find and load it automatically. You can
create your own plugin by inheriting from the Tem_
plate::Plugin module.
Here's an example which defines some data items ('foo' and
'people') and also an object method ('bar'). We'll call
the plugin 'FooBar' for want of a better name and create
it in the 'MyOrg::Template::Plugin::FooBar' package.
We've added a 'MyOrg' to the regular 'Template::Plugin::*'
package to avoid any conflict with existing plugins.
You can create a module stub using the Perl utlity h2xs:

h2xs -A -X -n MyOrg::Template::Plugin::FooBar
This will create a directory structure representing the
package name along with a set of files comprising your new
module. You can then edit FooBar.pm to look something
like this:

package MyOrg::Template::Plugin::FooBar;
use Template::Plugin;
use vars qw( $VERSION );
use base qw( Template::Plugin );
$VERSION = 1.23;
sub new {
my ($class, $context, @params) = @_;
bless {
_CONTEXT => $context,
foo => 25,
people => [ 'tom', 'dick', 'harry' ],
}, $class;
}
sub bar {
my ($self, @params) = @_;
# ...do something...
return $some_value;
}
The plugin constructor new() receives the class name as
the first parameter, as is usual in Perl, followed by a
reference to something called a Template::Context object.
You don't need to worry too much about this at the moment,
other than to know that it's the main processing object
for the Template Toolkit. It provides access to the func
tionality of the processor and some plugins may need to
communicate with it. We don't at this stage, but we'll
save the reference anyway in the '_CONTEXT' member. The
leading underscore is a convention which indicates that
this item is private and the Template Toolkit won't
attempt to access this member. The other members defined,
'foo' and 'people' are regular data items which will be
made available to templates using this plugin. Following
the context reference are passed any additional parameters
specified with the USE directive, such as the data source
parameter, 'dbi:mSQL:mydbname', that we used in the ear
lier DBI example.
If you used h2xs to create the module stub then you'll
already have a Makefile.PL and you can incite the familiar
incantation to build and install it. Don't forget to add
some tests to test.pl!

perl Makefile.PL
make
make test
make install
If you don't or can't install it to the regular place for
your Perl modules (perhaps because you don't have the
required privileges) then you can set the PERL5LIB envi
ronment variable to specify another location. If you're
using ttree then you can add the following line to your
configuration file instead. This has the effect of add
'/path/to/modules' to the @INC array to a similar end.
$HOME/.ttreerc:

perl5lib = /path/to/modules
One further configuration item must be added to inform the
toolkit of the new package name we have adopted for our
plugins:
$HOME/.ttreerc:

plugin_base = 'MyOrg::Template::Plugin'
If you're writing Perl code to control the Template mod
ules directly, then this value can be passed as a configu
ration parameter when you create the module.

use Template;
my $template = Template->new({
PLUGIN_BASE => 'MyOrg::Template::Plugin'
});
Now we can create a template which uses this plugin:

[% INCLUDE header
title = 'FooBar Plugin Test'
%]
[% USE FooBar %]
Some values available from this plugin:
[% FooBar.foo %] [% FooBar.bar %]
The users defined in the 'people' list:
[% FOREACH uid = FooBar.people %]
* [% uid %]
[% END %]
[% INCLUDE footer %]
The 'foo', 'bar' and 'people' items of the FooBar plugin
are automatically resolved to the appropriate data items
or method calls on the underlying object.
Using this approach, it is possible to create application
functionality in a single module which can then be loaded
and used on demand in any template. The simple interface
between template directives and plugin objects allows com
plex, dynamic content to be built from a few simple tem
plate documents without knowing anything about the under
lying implementation.

AUTHOR

Andy Wardley <abw@andywardley.com>

<http://www.andywardley.com/|http://www.andywardley.com/>

VERSION

Template Toolkit version 2.08, released on 30 July 2002.

COPYRIGHT

Copyright (C) 1996-2002 Andy Wardley. All Rights Re
served.
Copyright (C) 1998-2002 Canon Research Centre Europe
Ltd.
This module is free software; you can redistribute it
and/or modify it under the same terms as Perl itself.
Copyright © 2010-2025 Platon Technologies, s.r.o.           Home | Man pages | tLDP | Documents | Utilities | About
Design by styleshout