749 lines
26 KiB
Perl
749 lines
26 KiB
Perl
#============================================================= -*-perl-*-
|
|
#
|
|
# Template::Tutorial::Web
|
|
#
|
|
# DESCRIPTION
|
|
# Tutorial on generating web content with the Template Toolkit
|
|
#
|
|
# AUTHOR
|
|
# Andy Wardley <abw@wardley.org>
|
|
#
|
|
# COPYRIGHT
|
|
# Copyright (C) 1996-2008 Andy Wardley. All Rights Reserved.
|
|
#
|
|
# This module is free software; you can redistribute it and/or
|
|
# modify it under the same terms as Perl itself.
|
|
#
|
|
#========================================================================
|
|
|
|
=head1 NAME
|
|
|
|
Template::Tutorial::Web - Generating Web Content Using the Template Toolkit
|
|
|
|
=head1 Overview
|
|
|
|
This tutorial document provides a introduction to the Template 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
|
|
L<tpage|Template::Tools::tpage> and L<ttree|Template::Tools::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 L<Template>,
|
|
L<Template::Manual> and the various sections within it. e.g
|
|
|
|
perldoc Template # Template.pm module usage
|
|
perldoc Template::Manual # index to manual
|
|
perldoc Template::Manual::Config # e.g. configuration options
|
|
|
|
The documentation is also available in HTML format to read online, or download
|
|
from the Template Toolkit web site:
|
|
|
|
http://template-toolkit.org/docs/
|
|
|
|
=head1 Introduction
|
|
|
|
The Template Toolkit is a set of Perl modules which collectively
|
|
implement a template processing system.
|
|
|
|
A template is a text document with special markup tags embedded in it.
|
|
By default, the Template Toolkit uses 'C<[%>' and 'C<%]>' to denote
|
|
the start and end of a tag. Here's an example:
|
|
|
|
[% INCLUDE header %]
|
|
|
|
People of [% planet %], your attention please.
|
|
|
|
This is [% captain %] of the
|
|
Galactic Hyperspace Planning Council.
|
|
|
|
As you will no doubt be aware, the plans
|
|
for development of the outlying regions
|
|
of the Galaxy require the building of a
|
|
hyperspatial express route through your
|
|
star system, and regrettably your planet
|
|
is one of those scheduled for destruction.
|
|
|
|
The process will take slightly less than
|
|
[% time %].
|
|
|
|
Thank you.
|
|
|
|
[% INCLUDE footer %]
|
|
|
|
Tags can contain simple I<variables> (like C<planet> and C<captain>) and more
|
|
complex I<directives> that start with an upper case keyword (like C<INCLUDE>).
|
|
A directive is an instruction that tells the template processor to perform
|
|
some action, like processing another template (C<header> and C<footer> in this
|
|
example) and inserting the output into the current template. In fact, the
|
|
simple variables we mentioned are actually C<GET> directives, but the C<GET>
|
|
keyword is optional.
|
|
|
|
People of [% planet %], your attention please. # short form
|
|
People of [% GET planet %], your attention please. # long form
|
|
|
|
Other directives include C<SET> to set a variable value (the C<SET> keyword is
|
|
also optional), C<FOREACH> to iterate through a list of values, and C<IF>,
|
|
C<UNLESS>, C<ELSIF> and C<ELSE> to declare conditional blocks.
|
|
|
|
The Template Toolkit processes all I<text> files equally, regardless of what
|
|
kind of content they contain. So you can use TT to generate HTML, XML, CSS,
|
|
Javascript, Perl, RTF, LaTeX, or any other text-based format. In this tutorial,
|
|
however, we'll be concentrating on generating HTML for web pages.
|
|
|
|
=head1 Generating Static Web Content
|
|
|
|
Here's an example of a template used to generate an HTML document.
|
|
|
|
[% INCLUDE header
|
|
title = 'This is an HTML example';
|
|
|
|
pages = [
|
|
{ url = 'http://foo.org'
|
|
title = 'The Foo Organisation'
|
|
}
|
|
{ url = 'http://bar.org'
|
|
title = 'The Bar Organisation'
|
|
}
|
|
]
|
|
%]
|
|
<h1>Some Interesting Links</h1>
|
|
<ul>
|
|
[% FOREACH page IN pages %]
|
|
<li><a href="[% page.url %]">[% page.title %]</a>
|
|
[% END %]
|
|
</ul>
|
|
|
|
[% INCLUDE footer %]
|
|
|
|
This example shows how the C<INCLUDE> directive is used to load and process
|
|
separate 'C<header>' and 'C<footer>' template files, including the output in
|
|
the current document. These files might look something like this:
|
|
|
|
header:
|
|
|
|
<html>
|
|
<head>
|
|
<title>[% title %]</title>
|
|
</head>
|
|
<body>
|
|
|
|
footer:
|
|
|
|
<div class="copyright">
|
|
© Copyright 2007 Arthur Dent
|
|
</div>
|
|
</body>
|
|
</html>
|
|
|
|
The example also uses the C<FOREACH> directive to iterate through the
|
|
'C<pages>' list to build a table of links. In this example, we have defined
|
|
this list within the template to contain a number of hash references, each
|
|
containing a 'C<url>' and 'C<title>' member. The C<FOREACH> directive iterates
|
|
through the list, aliasing 'C<page>' to each item (in this case, hash array
|
|
references). The C<[% page.url %]> and C<[% page.title %]> directives then
|
|
access the individual values in the hash arrays and insert them into the
|
|
document.
|
|
|
|
=head2 Using tpage
|
|
|
|
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
|
|
L<tpage|Template::Tools::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 F<example.html>, you would run
|
|
the command:
|
|
|
|
$ tpage example.html
|
|
|
|
This will process the template file, sending the output to C<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 (e.g.
|
|
'C<.tt>') and another (e.g. 'C<.html>') for the output files.
|
|
|
|
$ tpage example.tt > example.html
|
|
|
|
Or you can redirect the output to another directory. e.g.
|
|
|
|
$ tpage templates/example.tt > html/example.html
|
|
|
|
The output generated would look like this:
|
|
|
|
<html>
|
|
<head>
|
|
<title>This is an HTML example</title>
|
|
</head>
|
|
<body>
|
|
<h1>Some Interesting Links</h1>
|
|
<ul>
|
|
<li><a href="http://foo.org">The Foo Organsiation</a>
|
|
<li><a href="http://bar.org">The Bar Organsiation</a>
|
|
</ul>
|
|
<div class="copyright">
|
|
© Copyright 2007 Arthur Dent
|
|
</div>
|
|
</body>
|
|
</html>
|
|
|
|
The F<header> and F<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.
|
|
|
|
=head2 Using ttree
|
|
|
|
The L<tpage|Template::Tools::tpage> script gives you a simple and easy way to
|
|
process a single template without having to write any Perl code. The
|
|
L<ttree:Template::Tools::ttree> script, also distributed as part of the
|
|
Template Toolkit, provides a more flexible way to process a number of template
|
|
documents in one go.
|
|
|
|
The first time you run the script, it will ask you if it should create a
|
|
configuration file (F<.ttreerc>) in your home directory. Answer C<y> to have
|
|
it create the file.
|
|
|
|
The L<ttree:Template::Tools::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.
|
|
|
|
In brief, the configuration file describes the directories in which template
|
|
files are to be found (C<src>), where the corresponding output should be
|
|
written to (C<dest>), and any other directories (C<lib>) that may contain
|
|
template files that you plan to C<INCLUDE> into your source documents. You can
|
|
also specify processing options (such as C<verbose> and C<recurse>) and provide
|
|
regular expression to match files that you don't want to process (C<ignore>,
|
|
C<accept>)> or should be copied instead of being processed as templates (C<copy>).
|
|
|
|
An example F<.ttreerc> file is shown here:
|
|
|
|
$HOME/.ttreerc:
|
|
|
|
verbose
|
|
recurse
|
|
|
|
# this is where I keep other ttree config files
|
|
cfg = ~/.ttree
|
|
|
|
src = ~/websrc/src
|
|
lib = ~/websrc/lib
|
|
dest = ~/public_html/test
|
|
|
|
ignore = \b(CVS|RCS)\b
|
|
ignore = ^#
|
|
|
|
You can create many different configuration files and store them
|
|
in the directory specified in the C<cfg> option, shown above. You then
|
|
add the C<-f filename> option to C<ttree> to have it read that file.
|
|
|
|
When you run the script, it compares all the files in the C<src> directory
|
|
(including those in sub-directories if the C<recurse> option is set), with
|
|
those in the C<dest> directory. 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 C<-a> option forces all files to be processed, regardless of
|
|
modification times.
|
|
|
|
The script I<doesn't> process any of the files in the C<lib> directory, but it
|
|
does add it to the C<INCLUDE_PATH> for the template processor so that it can
|
|
locate these files via an C<INCLUDE>, C<PROCESS> or C<WRAPPER> directive.
|
|
Thus, the C<lib> directory 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 L<ttree|Template::Tools::ttree> documentation and help
|
|
summary (C<ttree -h>) for full details. e.g.
|
|
|
|
$HOME/.ttreerc:
|
|
|
|
pre_process = config
|
|
interpolate
|
|
post_chomp
|
|
|
|
The C<pre_process> option allows you to specify a template file which
|
|
should be processed before each file. Unsurprisingly, there's also a
|
|
C<post_process> option to add a template after each file. In the
|
|
fragment above, we have specified that the C<config> template should be
|
|
used as a prefix template. We can create this file in the C<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 C<header> file.
|
|
|
|
$lib/config:
|
|
|
|
[% root = '~/abw'
|
|
home = "$root/index.html"
|
|
images = "$root/images"
|
|
email = 'abw@wardley.org'
|
|
graphics = 1
|
|
webpages = [
|
|
{ url => 'http://foo.org', title => 'The Foo Organsiation' }
|
|
{ url => 'http://bar.org', title => 'The Bar Organsiation' }
|
|
]
|
|
%]
|
|
|
|
Assuming you've created or copied the C<header> and C<footer> files from the
|
|
earlier example into your C<lib> directory, you can now start to create
|
|
web pages like the following in your C<src> directory and process them
|
|
with C<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. C<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 F<ttree>, you should see output similar to the following
|
|
(assuming you have the verbose flag set).
|
|
|
|
ttree 2.9 (Template Toolkit version 2.20)
|
|
|
|
Source: /home/abw/websrc/src
|
|
Destination: /home/abw/public_html/test
|
|
Include Path: [ /home/abw/websrc/lib ]
|
|
Ignore: [ \b(CVS|RCS)\b, ^# ]
|
|
Copy: [ ]
|
|
Accept: [ * ]
|
|
|
|
+ newpage.html
|
|
|
|
The C<+> in front of the C<newpage.html> filename shows that the file was
|
|
processed, 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 C<-> and giving a reason why the file wasn't processed.
|
|
|
|
- newpage.html (not modified)
|
|
|
|
It has detected a C<newpage.html> in the destination directory which is
|
|
more recent than that in the source directory and so hasn't bothered
|
|
to waste time re-processing it. To force all files to be processed,
|
|
use the C<-a> option. You can also specify one or more filenames as
|
|
command line arguments to C<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>
|
|
|
|
<a href="~/abw/index.html">Home</a>
|
|
<a href="mailto:abw@wardley.org">Email me</a>
|
|
<img src="~/abw/images/logo.gif" align=right width=60 height=40>
|
|
|
|
<div class="copyright">
|
|
© Copyright 2007 Arthur Dent
|
|
</div>
|
|
</body>
|
|
</html>
|
|
|
|
You can add as many documents as you like to the C<src> directory and
|
|
C<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
|
|
consistency in links, header style, or whatever else you choose to
|
|
implement in terms of common templates elements or variables.
|
|
|
|
=head1 Dynamic Content Generation Via CGI Script
|
|
|
|
The L<Template> module provides a simple front-end to the Template Toolkit for
|
|
use in CGI scripts and Apache/mod_perl handlers. Simply C<use> the L<Template>
|
|
module, create an object instance with the L<new()> method and then call the
|
|
L<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
|
|
variables that we want made available to the template:
|
|
|
|
#!/usr/bin/perl
|
|
use strict;
|
|
use warnings;
|
|
use Template;
|
|
|
|
my $file = 'src/greeting.html';
|
|
my $vars = {
|
|
message => "Hello World\n"
|
|
};
|
|
|
|
my $template = Template->new();
|
|
|
|
$template->process($file, $vars)
|
|
|| die "Template process failed: ", $template->error(), "\n";
|
|
|
|
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 environment:
|
|
|
|
my $template->new({
|
|
# where to find template files
|
|
INCLUDE_PATH => ['/home/abw/websrc/src', '/home/abw/websrc/lib'],
|
|
# pre-process lib/config to define any extra values
|
|
PRE_PROCESS => 'config',
|
|
});
|
|
|
|
Note that here we specify the C<config> file as a C<PRE_PROCESS> 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 definitions 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 C<process()> method.
|
|
|
|
These entries in this hash may contain simple text or other values,
|
|
references to lists, others hashes, sub-routines 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 C<$vars>, we create a reference to a
|
|
L<CGI> object and a C<get_user_projects()> sub-routine.
|
|
|
|
#!/usr/bin/perl
|
|
use strict;
|
|
use warnings;
|
|
use Template;
|
|
use CGI;
|
|
|
|
$| = 1;
|
|
print "Content-type: text/html\n\n";
|
|
|
|
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/websrc/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 IN worklist(me.id) %]
|
|
<li> <a href="[% project.url %]">[% project.name %]</a>
|
|
[% END %]
|
|
</ul>
|
|
|
|
[% INCLUDE footer %]
|
|
|
|
This example shows how we've separated the Perl implementation (code) from the
|
|
presentation (HTML). This 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
|
|
L<ttree|Template::Tools::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 application state.
|
|
|
|
=head1 Dynamic Content Generation Via Apache/Mod_Perl Handler
|
|
|
|
B<NOTE:> the L<Apache::Template> module is available from CPAN and provides a
|
|
simple and easy to use Apache/mod_perl interface to the Template Toolkit.
|
|
Although basic, it implements 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 customise processing for your own need, and
|
|
this section will show you how to get started.
|
|
|
|
The L<Template> module can be used from an Apache/mod_perl handler. Here's an
|
|
example of a typical Apache F<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 C</user/bin> to which all requests will
|
|
be forwarded to the C<handler()> method of the C<MyOrg::Apache::User>
|
|
module. That module might look something like this:
|
|
|
|
package MyOrg::Apache::User;
|
|
|
|
use strict;
|
|
use Apache::Constants qw( :common );
|
|
use Template qw( :template );
|
|
use CGI;
|
|
|
|
our $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:$websrc/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, $template->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 C<websrc_root>
|
|
value from the config file. This is then used to define an C<INCLUDE_PATH>
|
|
for a new L<Template> object. The URI is extracted from the request and a
|
|
L<CGI> object is created. These are both defined as template variables.
|
|
|
|
The name of the template file itself is taken from the C<PATH_INFO> element
|
|
of the request. In this case, it would comprise the part of the URL
|
|
coming after C</user/bin>, e.g for C</user/bin/edit>, the template file
|
|
would be C<edit> located in C<$websrc/src/user>. The headers are sent
|
|
and the template file is processed. All output is sent directly to the
|
|
C<print()> method of the Apache request object.
|
|
|
|
=head1 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
|
|
functionality in a separate module and then load and use it as
|
|
required with the C<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
|
|
C<tpage> or C<ttree>. You I<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 C<DBI> plugin written by Simon
|
|
Matthews (available from CPAN). You can create this template in your C<src>
|
|
directory and process it using C<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 IN 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
|
|
L<Template::Plugin> module.
|
|
|
|
Here's an example which defines some data items (C<foo> and C<people>)
|
|
and also an object method (C<bar>). We'll call the plugin C<FooBar> for
|
|
want of a better name and create it in the C<MyOrg::Template::Plugin::FooBar>
|
|
package. We've added a C<MyOrg> to the regular C<Template::Plugin::*> package
|
|
to avoid any conflict with existing plugins.
|
|
|
|
package MyOrg::Template::Plugin::FooBar;
|
|
use base 'Template::Plugin'
|
|
our $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 C<new()> receives the class name as the first
|
|
parameter, as is usual in Perl, followed by a reference to something called a
|
|
L<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 functionality 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 C<_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, C<foo> and C<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, C<dbi:mSQL:mydbname>, that we used in the earlier DBI
|
|
example.
|
|
|
|
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 environment variable to specify another location.
|
|
If you're using C<ttree> then you can add the following line to your
|
|
configuration file instead.
|
|
|
|
$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 L<Template> modules directly,
|
|
then this value can be passed as a configuration 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 C<foo>, C<bar>, and C<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 complex, dynamic content to be
|
|
built from a few simple template documents without knowing anything
|
|
about the underlying implementation.
|
|
|
|
=head1 AUTHOR
|
|
|
|
Andy Wardley E<lt>abw@wardley.orgE<gt> L<http://wardley.org/>
|
|
|
|
=head1 COPYRIGHT
|
|
|
|
Copyright (C) 1996-2007 Andy Wardley. All Rights Reserved.
|
|
|
|
This module is free software; you can redistribute it and/or
|
|
modify it under the same terms as Perl itself.
|
|
|
|
=cut
|
|
|
|
# Local Variables:
|
|
# mode: perl
|
|
# perl-indent-level: 4
|
|
# indent-tabs-mode: nil
|
|
# End:
|
|
#
|
|
# vim: expandtab shiftwidth=4:
|