Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

Template Toolkit 2

by Masem (Monsignor)
on Apr 14, 2001 at 16:57 UTC ( #72572=modulereview: print w/ replies, xml ) Need Help??

Item Description: A language-neutral templating system

Review Synopsis:

Item Description: Create text streams from Perl data and template files
Review Synopsis: An extremely powerful and extendable module that can be used to separate data presentation concerns from Perl code
Module Author: Andy Wardley
Module Homepage: http://www.template-toolkit.org/index.html

Description

Template Toolkit 2 (hence referred to as TT2) is a distribution of Perl modules that can be used to place Perl data into templates, similar to modules like HTML::Template, HTML::Mason, or Text::Template. However, unlike these other template modules, TT2 is language-neutral and can be used to generate output for any text-based language, include HTML, XML, PS, plain text, or what have you.

TT2 can be found on CPAN as a Distribution, and thus, can be easily installed on your system. It does take a while to compile support libraries, however. As there's no special system calls, TT2 should work on any platform that uses Perl. The documentation is well written and includes numerous examples of using TT2, and also has a mailing list for further support (available at the site above).

The Perl interface to TT2 is rather simple:

use Template; my $tt = Template-new(); $tt->process( $template_file , { scalar_param => $scalar, array_param => \@array, hash_param => \%hash } ) or die $tt->error();
The first parameter to process() is the file which your template is in; various configuration flags can have this located relative to your script, or in an absolute file location. The second parameter is an anonymous hash which can contain anything (within reason); the keys are used for further reference in the template file. An optional third parameter can be used to point the output to a predefined string, file, or other text stream; without this, the output is sent directly to STDOUT (very handy for CGI scripting).

The template itself may look something like this:

Hello [% name %], how are you doing on this fine [%- IF hour < 11 -%] morning [%- ELSIF hour < 18 -%] afternoon [%- ELSE -%] evening [%- END -%] ?
TT2 interprets everything between '[%' and '%]' itself, leaving other parts untouched. Because commands can sometimes extend onto multiple lines when the final output should not be, both the opening and closing delimiters can be marked to indicate if pre- or post-chomping should be done or not , as demonstrated in the IF block above. So if the above was processed, the final line would be contained on one single line.

Unless recognized as a keyword or a statement, TT2 will substitute whatever is between the delimiters with the value associated with that key in the hash passed as the second parameter in the process function. Deeply nested data structures can be recalled using name-dot-name like notation:

# # .. from perl .. # $tt()->process( 'text.tt', { data => ( name => 'John', age => '18', grades => ( 98, 57, 79 ) ) } ) or die $tt->error(); # # .. in template file .. # Hello, [% data.name %], your third test grade was [% data.grades.2 %] Your grades so far have been: [% FOREACH grade = data.grades %] [% grade %] [% END %]
In addition, you can assign and adjust variables within the template language if needed. If you pass object variables, you can also call their methods directly from the template file. You can also create variables that exist only within the template, and furthermore, you can allow TT2 to specify a configuration template that will be precluded for any other template that you call, a useful tool when several data streams will be generated but with common elements.

A large number of keywords (indicated as all-caps words) can be used for basic flow control, include IF-ELSIF-ELSE blocks, FOREACH blocks, and several others. You can also create template blocks, small bits of repeated code, and use INCLUDE statements to encourage code reuse. You can also define MARCOs to simplify parts of your input template file. Another powerful feature is the ability to use plug-ins for TT2, including one that gives you direct access to CGI.pm's functions, one to interface with DBI, and several XML ones. Since TT2 is language-neutral, there is no direct support for HTML or CGI forms, but the ability to access CGI.pm's features makes this a non-problem. There's also several other ways to extend the module beyond plug-ins to suit your needs.

Besides being very useful from Perl, TT2 comes with two perl scripts, "tpage" and "ttree", that can allow you to create a single page or a whole directory tree of files from template files. This can be helpful to maintain, for example, static portions of a web site to keep a consistent theme across it. External configuration files can also help change certain features without doing massive editing of several files.

One final key feature is the ability to include Perl code directly into the template file via the PERL directive. While this ability can be taken advantage of at any time, it easily allows one to create what are effectively embedded-perl pages, though some tweaking with the server will need to be done to make sure these are served efficently.

Benefits

The key benefit of TT2 over the other templating modules, as already mentioned, is it's language neutrality; other template modules tend to be tied to one language, but TT2 lacks that, though the current batch of plugins tend to favor HTML. TT2 has good caching support, which allows it to work quickly after initial processing in a persistent environment, such as in mod_perl.

With proper use of TT2 it should be very easy to separate details of output from your Perl code, thus making it easier to either debug the logic in the Perl script, or redesign the output through the templates. Doing such can lead to a rapid development and design environment for any Perl application that has much moving targets.

Numerous other benefits have been pointed out to by this node.

Pitfalls/Caveats

TT2 is not lightweight. When you initially load a template file, you'll get some delay as parsing and caching occur on the file. However, this can be easily avoided by taking proper steps to ensure that caching of the parsed files will be done (namely by keeping the instance variable around). While the caching may not be as fast as the other templating systems, it's understandable that a complex system such as this will take more time and resources to do it's job. In practical tests, once TT2 is caching the template files, it works at an outstanding pace.

A minor nit that I've had is that the process function defaults to STDOUT, as opposed to going to some output string. Mind you, this is also easily dealt with using a third parameter, but when print $cgi->f() calls are mixed with $tt->process statements, both sending output to STDOUT, it can be a bit confusing.

Conclusions

TT2 is an excellent module for plugging data into a template file for preparation for any sort of text stream output, thanks to it's language neutrality. Numerous control functions allow for a powerful scripting language which can be interfaced back with Perl. While TT2 may be a bit power-hungry, it should work fine on high load servers once it gets going, making it excellent not only for HTML delivery, but XML or any other custom format. In addition, as I hope to get to in a later article, it helps to create the ability to do rapid development of applications by separating logic from presentation.

Edited 2001-04-16 by Ovid

Comment on Template Toolkit 2
Select or Download Code
Re: Template Toolkit 2
by lachoy (Parson) on Apr 14, 2001 at 17:19 UTC

    Just a couple little things. About caching: TT2 compiles a template to a Perl subroutine and caches it, which is very fast indeed! It also allows you to save this Perl subroutine to disk so the next time a system like mod_perl starts up you don't even have to parse the template. Sweet! (Yes, I'm a big fan of TT.)

    Another nifty benefit that you touched on briefly is the consistent notation for variable access. For instance you can start out a template using a hash user:

    my $tmpl = Template->new(); $tmpl->process( 'user_form.tmpl', { user => { name => 'Bruce Springsteen', last_login => '2000-01-01 05:45:00' }, common_date_format => \&my_date_format } );

    user_form.tmpl

    <p>Welcome [% user.name %]. Your last login was [% common_date_format( user.last_login ) %].</p>

    Later, you might want to make user an object which has the methods name() and last_login():

    my $user = User->fetch( 'theboss' ); my $tmpl = Template->new(); $tmpl->process( 'user_form.tmpl', { user => $user, common_date_format => \&my_date_format } );

    This requires no modification to your template, which makes refactoring a larger system a more palatable task.

    Chris
    M-x auto-bs-mode

Back to Reviews

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: modulereview [id://72572]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (4)
As of 2014-07-26 03:55 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My favorite superfluous repetitious redundant duplicative phrase is:









    Results (175 votes), past polls