O'Reilly logo

Perl Template Toolkit by David Cross, Andy Wardley, Darren Chamberlain

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

Chapter 4. Template Directives

Templates consist of a combination of fixed text and template directives. The template directives are recognized by the Template Toolkit and are expanded in a processor’s output. In this chapter, we will take a close look at all of the directives that the Template Toolkit provides. We’ve already seen examples of many of them in previous chapters, but now we’ll go back and fill in all of the details.

The Template Toolkit has directives for common presentation tasks. There are directives for accessing and setting variables, loading and using both external and local templates, repetition, conditional processing, flow control, and exception handling. Directives are also provided to define macros and access template metadata. If that’s not enough for you, you can extend the functionality of the Template Toolkit using filters, plugins, or even inline Perl code.

Accessing Variables

The Template Toolkit allows you to define variables in your templates. In this section, we will look at the various directives that the Template Toolkit provides for manipulating template variables.

GET

The GET directive retrieves and outputs the value of the named variable:

[% GET foo %]

The GET keyword is optional. A variable can be specified in a directive tag by itself:

[% foo %]

The variable name can have an unlimited number of elements, each separated by a . (dot). Each element can have arguments specified within parentheses:

[% foo %]
[% bar.baz %]
[% biz.baz(10) %]

See Chapter 3 for a full discussion of template variables.

The GET directive can also take an expression as an argument:

[% GET total + tax %]

[% GET length * breadth * height %]

Expressions can use any of the mathematical operators +, -, *, /, mod, div, and %. They can be combined using the logical operators and, or, and not. &&, ||, and ! are provided as aliases for and, or, and not.

[% GET golgafrincham.answer or 42 %]

The mod, div, and % operators carry out integer division. div returns the result of the division and mod returns the modulus (or remainder) from the division:

[% SET people = 4
       pies = 10 %]

[% pies %] pies shared between [% people %] people
is [% pies div people %] pies each
(and [% pies mod people %] pies left over)

The % operator is a synonym for mod.

The logical operator ?: is also available:

[% pies > people * 2 ? 'everyone happy' : 'not enough pies' %]

This operator works by evaluating the expression that comes before the question mark to see if it is true or false. If it is true, the operator returns the expression that comes before the : character. If it is false, the operator returns the expression that follows the : character. In the example, status is set to either everyone happy or not enough pies depending on whether we have at least two pies for everyone.

The comparison operators = =, !=, <, <=, >, and >= are also provided. Note that they always compare their operands as strings.

[% GET name =  = 'Zaphod' ?
               'Greetings Mr. President' :
               'Hello Monkey' %]

SET

The SET directive allows you to assign new values to existing variables or to create new temporary variables:

[% SET title = 'Hello World' %]

The SET keyword is optional when it is unambiguous:

[% title = 'Hello World' %]

Variables may be assigned the values of other variables, unquoted numbers (digits), literal text (single quotes), or quoted text (double quotes). In the latter case, any variable references within the text will be interpolated when the string is evaluated. Variables should be prefixed by $, using curly braces to explicitly scope the variable name where necessary.

[% foo  = 'Foo'  %]               # literal value 'Foo'
[% bar  =  foo   %]               # value of variable 'foo'
[% cost = '$100' %]               # literal value '$100'
[% item = "$bar: ${cost}.00" %]   # value "Foo: $100.00"

Multiple variables may be assigned in the same directive and are evaluated in the order specified. Thus, the previous example could have been written:

[% foo  = 'Foo'
   bar  = foo
   cost = '$100'
   item = "$bar: ${cost}.00"
%]

Simple expressions can also be used, as they can with GET:

[% ten    = 10 
   twenty = 20
   thirty = twenty + ten
   forty  = 2 * twenty 
   fifty  = 100 div 2
   six    = twenty mod 7
%]

You can concatenate strings together using the underscore (_) operator. In Perl 5, the . is used for string concatenation, but in Perl 6, as in the Template Toolkit, the . will be used as the method-calling operators and the underscore (_) operator will be used for string concatenation.[7] Note that the operator must be specified with surrounding whitespace that, as Larry says, is construed as a feature:

[% copyright = '(C) Copyright ' _ year _ ' ' _ author %]

You can, of course, achieve a similar effect with double-quoted string interpolation:

[% copyright = "(C) Copyright $year $author" %]

The SET directive can also take arguments that are expressions in exactly the same way as the GET directive:

[% total = price + (price * tax_rate) %]

CALL

The CALL directive is similar to GET in evaluating the variable named, but doesn’t print the result returned. This can be useful when a variable is bound to a subroutine or object method that you want to call but whose returned value you aren’t interested in.

[% CALL dbi.disconnect %]

[% CALL inc_page_counter(page_count) %]

DEFAULT

The DEFAULT directive is similar to SET but updates only variables that are currently undefined or have no “true” value (in the Perl sense):

[% DEFAULT
   name = 'John Doe'
   id   = 'jdoe'
%]

This can be particularly useful in common template components to ensure that some sensible default is provided for otherwise undefined variables. If a true value is provided for variables with DEFAULT values, the provided value will be used; otherwise, the default value will be used.

[% DEFAULT 
   title = 'Hello World'
   bgcol = '#ffffff'
%]
<html>
<head>
<title>[% title %]</title>
</head>

<body bgcolor="[% bgcol %]">

DEFAULT can also take an expression as an argument in exactly the same way as GET:

[% DEFAULT pies = 3 * people %]

DEFAULT has no effect on variables that already have values.

Accessing External Templates and Files

Variables are for storing little bits of data. Templates are for writing larger chunks of content. As with variables, it is often useful to be able to reuse the contents of a template. For example, the output of a template will often actually be composed of the output of a number of lower-level templates. These lower-level templates can be reused in other templates. This is very similar to the modular approach to writing programs that encourages code reuse.

The Template Toolkit provides a number of directives for manipulating templates. The first three of these all work in a very similar way. INSERT, PROCESS, and INCLUDE all insert the contents of another named template into the current template. The basic syntax for these directives looks like this:

[% INCLUDE filename %]

You may optionally include arguments (in a name = value format) that define variables to use while processing the included template:

[% INCLUDE filename title = "la la la"
                    moonphase = "waxing" %]

With all of these directives, the results of processing the template are included in the output in place of the directive. The WRAPPER directive works a little differently. It is a block directive and it allows you to define a template that is wrapped around the block of content. The content of the block is made available to the wrapper template in a special variable called content.

[% WRAPPER layout %]
  blah blah 
[% END %]

We discuss the directives for manipulating templates in the next four sections.

INSERT

The INSERT directive is used to insert the contents of an external file at the current position:

[% INSERT myfile %]

No attempt to parse or process the file is made. The contents, possibly including any embedded template directives, are inserted intact.

The filename specified should be relative to one of the INCLUDE_PATH directories. Absolute (i.e., starting with /) and relative (i.e., starting with .) filenames may be used if the ABSOLUTE and RELATIVE options are set, respectively. Both of these options are disabled by default.

my $tt = Template->new({
    INCLUDE_PATH => '/here:/there:/every/where',
});

$tt->process('myfile');

The contents of myfile are:

[% INSERT foo %]            # looks for /here/foo then /there/foo
[% INSERT /etc/passwd %]    # file error: ABSOLUTE not set
[% INSERT ../secret %]      # file error: RELATIVE not set

For convenience, the filename does not need to be quoted as long as it contains only alphanumeric characters, underscores, dots, or forward slashes. Names containing any other characters should be quoted.

[% INSERT misc/legalese.txt            %]
[% INSERT 'dos98/Program Files/foobar' %]

To evaluate a variable to specify a filename, you should explicitly prefix it with a $ or use double-quoted string interpolation:

[% language = 'en'
   legalese = 'misc/legalese.txt' 
%]

[% INSERT $legalese %]              # 'misc/legalese.txt'
[% INSERT "$language/$legalese" %]  # 'en/misc/legalese.txt'

Multiple files can be specified using + as a delimiter. All files should be unquoted names or quoted strings. Any variables should be interpolated into double-quoted strings.

[% INSERT legalese.txt + warning.txt %]
[% INSERT  "$legalese" + warning.txt %]  # requires quoting

INCLUDE

The INCLUDE directive is used to process and include the output of another template file or block:

[% INCLUDE header %]

If a BLOCK of the specified name is defined in the same file or in a file from which the current template has been called (i.e., a parent template), it will be used in preference to any file of the same name.

[% INCLUDE table %]             # uses BLOCK defined below

[% BLOCK table %]
   <table>
   ...
   </table>
[% END %]

If a BLOCK definition is not currently visible, the template name should be a file relative to one of the INCLUDE_PATH directories, or an absolute or relative filename if the ABSOLUTE / RELATIVE options are appropriately enabled. The INCLUDE directive automatically quotes the filename specified, as per INSERT described earlier. When a variable contains the name of the template for the INCLUDE directive, it should be explicitly prefixed by $ or double-quoted:

[% myheader = 'my/misc/header' %]
[% INCLUDE   myheader  %]            # 'myheader'
[% INCLUDE  "myheader" %]            # 'myheader'
[% INCLUDE  $myheader  %]            # 'my/misc/header'
[% INCLUDE "$myheader" %]            # 'my/misc/header'

Any template directives embedded within the file will be processed accordingly. All variables currently defined will be visible and accessible from within the included template.

[% title = 'Hello World' %]
[% INCLUDE header %]
<body>
...

Therefore, this header template:

<html>
<title>[% title %]</title>

provides the following output:

<html>
<title>Hello World</title>
<body>
...

Local variable definitions may be specified after the template name, temporarily masking any existing variables. Insignificant whitespace is ignored within directives, so you can add variable definitions on the same line, on the next line, or split across several lines with comments interspersed, if you prefer.

[% INCLUDE table %]

[% INCLUDE table title="Active Projects" %]

[% INCLUDE table 
     title   = "Active Projects" 
     bgcolor = "#80ff00"    # chartreuse
     border  = 2
%]

The INCLUDE directive localizes (i.e., copies) all variables before processing the template. Any changes made within the included template will not affect variables in the including template.

[% foo = 10 %]

foo is originally [% foo %]
[% INCLUDE bar %]
foo is still [% foo %]

[% BLOCK bar %]
   foo was [% foo %]
   [% foo = 20 %]
   foo is now [% foo %]
[% END %]

The preceding example produces the following output:

foo is originally 10
   foo was 10
   foo is now 20
foo is still 10

Tip

The localization of the stash (that is, the process by which variables are copied before an INCLUDE to prevent being overwritten) is only skin-deep. The top-level variable namespace (hash) is copied, but no attempt is made to perform a deep-copy of other structures (hashes, arrays, objects, etc.). Therefore, a foo variable referencing a hash will be copied to create a new foo variable that points to the same hash array. Thus, if you update compound variables (e.g., foo.bar), you will change the original copy, regardless of any stash localization. If you’re not worried about preserving variable values, or you trust the templates you’re including, you might prefer to use the PROCESS directive, which is faster by virtue of not performing any localization.

You can specify dotted variables as “local” variables to an INCLUDE directive. However, be aware that because of the localization issues explained earlier (if you skipped the previous Note, you might want to go back and read it, or else skip this section too), the variables might not actually be “local.” If the first element of the variable name already references a hash array, the variable update will affect the original variable.

[% foo = {
       bar = 'Baz'
   }
%]

[% INCLUDE somefile foo.bar='Boz' %]

[% foo.bar %]           # Boz

This behavior can be a little unpredictable (and may well be improved upon in a future version). If you know what you’re doing with it and you’re sure that the variables in question are defined (nor not) as you expect them to be, you can rely on this feature to implement some powerful “global” data-sharing techniques. Otherwise, you might prefer to steer clear and always pass simple (undotted) variables as parameters to INCLUDE and other similar directives.

If you want to process several templates simultaneously, you can specify each of their names (quoted or unquoted names only, no unquoted $variables) joined together by +. The INCLUDE directive will then process them in order.

[% INCLUDE html/header + "site/$header" + site/menu
     title = "My Groovy Web Site"
%]

The variable stash is localized once and then the templates specified are processed in order, all within that same variable context. This makes it slightly faster than specifying several separate INCLUDE directives (because you clone the variable stash only once instead of n times), but it’s not quite as “safe” because any variable changes in the first file will be visible in the second, third, and so on. This might be what you want, of course, but then again, it might not.

PROCESS

The PROCESS directive is similar to INCLUDE but does not perform any localization of variables before processing the template. Any changes made to variables within the included template will be visible in the including template. For example, this code:

[% foo = 10 %]

foo is [% foo %]
[% PROCESS bar %]
foo is [% foo %]

[% BLOCK bar %]
   [% foo = 20 %]
   changed foo to [% foo %]
[% END %]

produces this output:

foo is 10
   changed foo to 20
foo is 20

Parameters may be specified in the PROCESS directive, but these too will become visible changes to current variable values. As such, the following code:

[% foo = 10 %]
foo is [% foo %]
[% PROCESS bar
   foo = 20 
%]
foo is [% foo %]

[% BLOCK bar %]
   this is bar, foo is [% foo %]
[% END %]

produces the following output:

foo is 10
   this is bar, foo is 20
foo is 20

The PROCESS directive is slightly faster than the INCLUDE directive because it avoids the need to localize (i.e., copy) the variable stash before processing the template. As with INSERT and INCLUDE, the first parameter does not need to be quoted as long as it contains only alphanumeric characters, underscores, periods, or forward slashes. A $ prefix can be used to explicitly indicate a variable that should be interpolated to provide the template name:

[% myheader = 'my/misc/header' %]
[% PROCESS  myheader %]              # 'myheader'
[% PROCESS $myheader %]              # 'my/misc/header'

As with INCLUDE, multiple templates can be specified, delimited by +, and are processed in order:

[% PROCESS html/header + my/header %]

WRAPPER

It’s not unusual to find yourself adding common headers and footers to pages or sub-sections within a page. For example:

[% INCLUDE section/header
   title = 'Quantum Mechanics'
%]
   Quantum mechanics is a very interesting subject which 
   should prove easy for the layman to fully comprehend.
[% PROCESS section/footer %]

[% INCLUDE section/header
   title = 'Desktop Nuclear Fusion for Under $50'
%]
   This describes a simple device that generates significant 
   sustainable electrical power from common tap water via the process 
   of nuclear fusion.
[% PROCESS section/footer %]

The individual template components being included might look like the folowing examples:

section/header:

<p>
<h2>[% title %]</h2>

section/footer:

</p>

The WRAPPER directive provides a way of simplifying this a little. It encloses a block to a matching END directive, which is first processed to generate some output. This is then passed to the named template file or BLOCK as the content variable.

[% WRAPPER section
   title = 'Quantum Mechanics'
%]
   Quantum mechanics is a very interesting subject which 
   should prove easy for the layman to fully comprehend.
[% END %]

[% WRAPPER section
   title = 'Desktop Nuclear Fusion for Under $50'
%]
   This describes a simple device that generates significant 
   sustainable electrical power from common tap water via the process 
   of nuclear fusion.
[% END %]

The single section template can then be defined as:

<p>
<h2>[% title %]</h2>
[% content %]
</p>

Like other block directives, it can be used in side-effect notation:

[% INSERT legalese.txt WRAPPER big_bold_table %]

It’s also possible to specify multiple templates to a WRAPPER directive. The specification order indicates outermost to innermost wrapper templates. For example, given the following template block definitions:

[% BLOCK bold   %]<b>[% content %]</b>[% END %]
[% BLOCK italic %]<i>[% content %]</i>[% END %]

the directive:

[% WRAPPER bold + italic %]Hello World[% END %]

would generate the following output:

<b><i>Hello World</i></b>

Defining Local Template Blocks

Sometimes, particularly in a project that involves a large number of small templates, it doesn’t seem very efficient to create an external file for every template that you need. The BLOCK ... END construct can be used to avoid this. It allows you to define template component blocks that can be processed with the INCLUDE, PROCESS, and WRAPPER directives.

[% BLOCK tabrow %]
<tr><td>[% name %]<td><td>[% email %]</td></tr>
[% END %]

<table>
[% PROCESS tabrow  name='Fred'  email='fred@nowhere.com' %]
[% PROCESS tabrow  name='Alan'  email='alan@nowhere.com' %]
</table>

A BLOCK definition can be used before it is defined, as long as the definition resides in the same file. The block definition itself does not generate any output.

[% PROCESS tmpblk %]

[% BLOCK tmpblk %] This is OK [% END %]

You can use an anonymous BLOCK to capture the output of a template fragment:

[% julius = BLOCK %]
   And Caesar's spirit, ranging for revenge,
   With Ate by his side come hot from hell,
   Shall in these confines with a monarch's voice
   Cry  'Havoc', and let slip the dogs of war;
   That this foul deed shall smell above the earth
   With carrion men, groaning for burial.
[% END %]

Like a named block, an anonymous block can contain any other template directives that are processed when the block is defined. The output generated by the block is then assigned to the variable julius.

Anonymous BLOCKs can also be used to define block macros. The enclosing block is processed each time the macro is called.

[% MACRO locate BLOCK %]
   The [% animal %] sat on the [% place %].
[% END %]

[% locate(animal='cat', place='mat') %]    # The cat sat on the mat
[% locate(animal='dog', place='log') %]    # The dog sat on the log

Loops

It is very common to want to repeat parts of a template. You might want to produce similar output for every item in a list, or you might want to repeat a piece of content a set number of times. The Template Toolkit provides two loop directives that deal with both of these situations—FOREACH (also spelled FOR) and WHILE.

Use FOREACH in cases where you know the size of the data set over which you are iterating, or in cases where you need access to loop metadata, such as the next or previous element, the index of the iteration, or the size of the data set. WHILE is useful for performing an action until a condition is true, for looping over a very large data set, or when termination of the loop depends on a condition external to the data set. Both directives are discussed in the sections that follow.

FOREACH

The FOREACH directive defines a block, up to the corresponding END tag, that is processed repeatedly for each item in a list. The basic syntax is:

[% FOREACH item IN list %]
   # content of block
[% END %]

You can also use = in place of IN if you find that more natural:

[% FOREACH item = list %]
   # content of block
[% END %]

FOREACH loops over each element in a list and creates an alias to the current item:

[% numbers = [ 1 .. 5 ] %]

[% FOREACH num IN numbers %]
    * [% num %]
[% END %]

In this example, numbers is an array of five elements, the numbers 1 through 5. In the FOREACH loop, these elements are assigned to num, one at a time, in the order that they occur in numbers:

* 1
* 2
* 3
* 4
* 5

Complex data

The elements of the array can be any kind of complex data:

[% fabfour = [
     {
       name       = "John Lennon"
       instrument = "guitar"
     }
     {
       name       = "Paul McCartney"
       instrument = "bass guitar"
     }
     {
       name       = "George Harrison"
       instrument = "lead guitar"
     }
     {
       name       = "Ringo Starr"
       instrument = "drums"
     }
   ]
%]
[% FOREACH beatle IN fabfour -%]
    [% beatle.name %] played [% beatle.instrument %].
[% END %]

The beatle variable is aliased to each hash in the fabfour list, and through it we can access the various elements:

John Lennon played guitar.
Paul McCartney played bass guitar.
George Harrison played lead guitar.
Ringo Starr played drums.

The original array is not modified, but the elements of the array can be modified within the FOREACH loop.

Importing hash array items

When the FOREACH directive is used without specifying a target variable, any iterated values that are hash references will be automatically imported:

[% FOREACH fabfour -%]
    [% name %] played [% instrument %].
[% END %]

This particular usage creates a localized variable context to prevent the imported hash keys from overwriting any existing variables. The imported definitions and any other variables defined in such a FOREACH loop will be lost at the end of the loop, when the previous context and variable values are restored.

Iterating over entries in a hash array

The FOREACH directive can also be used to iterate over the entries in a hash array. Each entry in the hash is returned in sorted order (based on the key) as a hash array containing “key” and “value” items.

[% users = {
     tom   = 'Thomas'
     dick  = 'Richard'
     larry = 'Lawrence'
   }
%]

[% FOREACH user IN users %]
   * [% user.key %] : [% user.value %]
[% END %]

The previous example generates the following output:

* dick : Richard    
* larry : Lawrence    
* tom : Thomas

To iterate over the keys of a hash, use the keys virtual method on the hash:

[% FOREACH key IN hash.keys %]
    * [% key %] : [% hash.$key %]
[% END %]

The loop iterator object

The underlying implementation of the FOREACH directive involves the creation of a special object called an iterator, which maintains metadata about the data set being processed. This object can be accessed within the body of the FOREACH using the special variable loop:

[% FOREACH item IN items %]
    [% IF loop.first %]
      <ul> 
    [% END %]
        <li>[% item %] ([% loop.count %] of [% loop.size %])</li>
    [% IF loop.last %]
      </ul>
    [% END %]
[% END %]

The iterator defines several useful methods that return information about the current loop:

size

Returns the size of the data set, or returns undef if the dataset has not been defined

max

Returns the maximum index number (i.e., the index of the last element), which is equivalent to size - 1

index

Returns the number of the current item, in the range 0 to max

count

Returns the current iteration count in the range 1 to size, equivalent to index + 1

first

Returns a Boolean value to indicate whether the iterator is currently on the first iteration of the set

last

Returns a Boolean value to indicate whether the iterator is currently on the last iteration of the set

prev

Returns the previous item in the data set, or returns undef if the iterator is on the first item

next

Returns the next item in the data set, or undef if the iterator is on the last item

An iterator plugin is available that enables you to control how an iterator is created; if an iterator object is passed to a FOREACH loop, it is used as is (a new iterator is not created).

[% USE all_data = iterator(list_one.merge(list_two)) %]
[% FOREACH datum = all_data %]
    ...
[% END %]

Nested FOREACH loops

Nested loops will work as expected, with the loop variable correctly referencing the innermost loop and being restored to any previous value (i.e., an outer loop) at the end of the loop:

[% FOREACH group IN grouplist;
       # loop => group iterator
       "Groups:\n" IF loop.first;

       FOREACH user IN group.userlist;
           # loop => user iterator
           "$loop.count: $user.name\n";
       END;

       # loop => group iterator
       "End of Groups\n" IF loop.last;
   END 
%]

The iterator plugin can also be used to explicitly create an iterator object. This can be useful within nested loops where you need to keep a reference to the outer iterator within the inner loop. The iterator plugin effectively allows you to create an iterator by a name other than loop. See the manpage for Template::Plugin::Iterator for further details.

[% USE giter = iterator(grouplist) %]

[% FOREACH group IN giter %]
   [% FOREACH user IN group.userlist %]
         user #[% loop.count %] in
         group [% giter.count %] is
         named [% user.name %]
   [% END %]
[% END %]

WHILE

WHILE loops are used to repeatedly process a template block. This block is enclosed within [% WHILE (test) %] ... [% END %] blocks and can be arbitrarily complex. The test condition follows the same rules as those for IF blocks.

[%  total = 0;
    WHILE total <= 100 %]
        Total: [% total;
        total = total + 1;
    END;
%]

An assignment can be enclosed in parentheses to evaluate the assigned value:

[% WHILE (user = next_user) %]
   [% user.name %]
[% END %]

The Template Toolkit uses a fail-safe counter to limit the number of loop iterations to prevent runaway loops that never terminate. If the loop exceeds 1,000 iterations, an undef exception will be thrown, reporting the error:

WHILE loop terminated (> 1000 iterations)

This number can be adjusted from within Perl by setting the $Template::Directive::WHILE_MAX variable.

Flow control: NEXT and LAST

The NEXT directive starts the next iteration in a FOREACH or WHILE loop:

[% FOREACH user IN userlist %]
   [% NEXT IF user.isguest %]
   Name: [% user.name %]    Email: [% user.email %]
[% END %]

The LAST directive can be used to prematurely exit the loop. BREAK is also provided as an alias for LAST.

[% FOREACH match IN results.nsort('score').reverse %]
   [% LAST IF match.score < 50 %]
   [% match.score %] : [% match.url %]
[% END %]

See the section titled Section 4.11 later in this chapter for more details.

Conditionals

Often you don’t know exactly what output is required until you process the template. Perhaps your web site should be orange on certain days of the week, or maybe negative numbers should be displayed in red. The Template Toolkit has a number of conditional directives that allow your template to make decisions about what path to take.

A conditional controls execution of a block of code, based on the value of a variable. In the Template Toolkit, there are two main conditional directives: IF and SWITCH. In addition, there is the UNLESS directive, which is a negated IF.

IF, ELSIF, ELSE, and UNLESS

The primary directive for conditional execution is the IF statement. The basic syntax is:

[% IF test %]
    action
[% END %]

where action is executed only if test is true (the Template Toolkit’s definition of “truth” is explained later in this section). IF statements allow for an optional ELSE clause, which is executed if test is not true. There can be multiple test/action pairs as well; these are written using the ELSIF statement:

[% IF today =  = "friday" %]
    Yay! It's Friday!
[% ELSIF today =  = "monday" %]
    Yuck.  It's Monday.
[% ELSE %]
    ...
[% END %]

There can be any number of ELSIF clauses, including none. The ELSE clause is also optional. Because the IF directive defines a block, the END token is not optional.

The test clause can be any statement, even just a single variable name; the extreme case is a test clause of 1—i.e., always true. If the result of this statement is 0 or “” (the empty string), test is considered to be false; everything else is true. Variables that have not been assigned a value, either with DEFAULT or SET, are considered to be false (the value of an undefined variable is an empty string).

More complex statements are possible, such as the earlier example. test can be arbitrarily complex. Other than simple variable value, another common test is equality or comparison: what value does a variable contain? The notation = = is used to compare strings because = is used for assignment—it is an error to try to assign to a variable in an IF statement, to prevent subtle errors and hard-to-diagnose problems. Comparison operators include:

=  =          Test for equality
!=          Test for inequality
<           Less than
<=          Less than or equal to
>           Greater than       
>=          Greater than or equal to
&&, AND     grouping
||, OR      grouping
!, NOT      negation

Some of these make sense only for numbers, such as >, >=, <, and <=. NOT is used to reverse the meaning of a test:

[% IF NOT today %]
    Error! 'today' not defined!
[% END %]

There is a special version of IF that does exactly this: UNLESS.

[% UNLESS today %]
    ...

UNLESS is exactly equivalent to IF NOT, and often clarifies the intent of the condition (but can be more confusing when combined with ELSIF clauses, even though this is a syntactically legal thing to do).

AND and OR can be used to construct compound statements that might otherwise require nested IF blocks:

[% IF today =  = "Friday" AND time >= 1700 %]
    Go home!  It's the weekend!
[% END %]

Without grouping, this would need to be:

[% IF today =  = "Friday" %]
    [% IF time >= 1700 %]
        Go home!  It's the weekend!
    [% END %]
[% END %]

As you can imagine, this would get very tedious for blocks with many options.

SWITCH and CASE

The SWITCH directive makes writing long IF / ELSIF / ELSE statements easier when the test condition needs to be compared to a number of possible outcomes. SWITCH consists of a single statement, which is evaluated once, and a number of CASE statements, against which the evaluated value is compared. For example:

[% SWITCH today %]
    [% CASE "Monday" %]
    Hi ho, hi ho, it's off to work we go.

    [% CASE "Friday" %]
    Friday's here, almost time for the weekend!

    [% CASE [ "Saturday" "Sunday" ] %]
    It's the weekend! Party!

    [% CASE %]
    Ho hum, just another workday...
[% END %]

The value in today is compared against each successive CASE statement until a match is found; the contents of the matching CASE statement are processed, or the contents of the default CASE statement are processed if no match is found (if there is a default CASE statement, of course). An equivalent IF / ELSIF / ELSE block would look like this:

[% IF today =  = "Saturday" OR today =  = "Sunday" %]
    It's the weekend! Party!
[% ELSIF today =  = "Monday" %]
    Hi ho, hi ho, it's off to work we go.
[% ELSIF today =  = "Friday" %]
    Friday's here, almost time for the weekend!
[% ELSE %]
    Ho hum, just another workday...
[% END %]

The SWITCH statement is cleaner and there is less syntax to maintain. Most important, however, is that if the test statement requires computation instead of just variable comparison, the SWITCH will be more efficient and has less potential for side effects.

Filters

One of the problems with templates is that you can never be completely sure what content will be produced at the end. This is particularly true if you are pulling in some of your data from an external source. Perhaps you are producing an HTML page from news stories that have been entered into a database by reporters. You can’t be sure the stories don’t contain characters such as < or & that should be plain text but will be interpreted as HTML. Or perhaps you have room for only a certain number of characters and you don’t know how long a story will be.

The Template Toolkit provides filters to deal with these cases. A filter can be applied to part of a template and will postprocess those parts in a defined manner. For example, the html filter converts troublesome characters to their equivalent HTML entities, and the truncate filter will truncate text to a given length.

The FILTER directive introduces a filter, which operates on a block:

[% FILTER html %]
   HTML text may have < and > characters embedded
   that you want converted to the correct HTML entities.
[% END %]

The previous example produces the following output:

HTML text may have &lt; and &gt; characters embedded
that you want converted to the correct HTML entities.

The FILTER directive can also follow various other nonblock directives. For example:

[% INCLUDE mytext FILTER html %]

The | character can also be used as an alias for FILTER:

[% INCLUDE mytext | html %]

Multiple filters can be chained together and will be called in sequence:

[% INCLUDE mytext FILTER html FILTER html_para %]

or:

[% INCLUDE mytext | html | html_para %]

A number of standard filters are provided with the Template Toolkit; these are detailed in Chapter 5.

Plugins

It is obviously impossible for the Template Toolkit to do everything that everyone might want to do with it. For one thing, we haven’t heard of every possible piece of software that you might want to talk to, and for another, no one would want a template processor that is infinite in size! Instead, we provided the plugin mechanism, which makes it possible to write extensions to the Template Toolkit. This is a far saner solution.

Plugins are externally defined extensions that can be dynamically loaded into templates to provide functionality. A plugin is a regular Perl module that conforms to a particular object-oriented interface, allowing it to be loaded into and used automatically by the Template Toolkit. The next subsections discuss directives for working with plugins.

USE

The USE directive loads and initializes “plugin” extension modules:

[% USE date %]

This makes a date plugin object available to the template, which can be used by referencing the variable date:

Today is [% date.format(date.now, "%A") %].

which might return:

Today is Monday.

The plugin name is case sensitive and will be appended to the PLUGIN_BASE value (which defaults to Template::Plugin) to construct a full module name. Any periods (i.e., .), in the name will be converted to ::.

[% USE MyPlugin %]     #  => Template::Plugin::MyPlugin
[% USE Foo.Bar  %]     #  => Template::Plugin::Foo::Bar

Various standard plugins are included with the Template Toolkit (see Chapter 6). These can be specified in lowercase and are mapped to the appropriate name:

[% USE cgi   %]        # => Template::Plugin::CGI
[% USE table %]        # => Template::Plugin::Table

Any additional parameters supplied in parentheses after the plugin name also will be passed to the new( ) constructor. A reference to the current Template::Context object is always passed as the first parameter. Thus:

[% USE MyPlugin('foo', 123) %]

is equivalent to:

Template::Plugin::MyPlugin->new($context, 'foo', 123);

Named parameters may also be specified. These are collated into a hash that is passed by reference as the last parameter to the constructor, as per the general code-calling interface. Thus:

[% USE url('/cgi-bin/foo', mode='submit', debug=1) %]

is equivalent to:

Template::Plugin::URL->new($context, '/cgi-bin/foo',
                           { mode => 'submit', debug => 1 });

The plugin may represent any data type—a simple variable, hash, list, or code reference—but in general it will be an object reference. Methods can be called on the object (or on the relevant members of the specific data type) in the usual way:

[% USE table(mydata, rows=3) %]

[% FOREACH row = table.rows %]
   <tr>    
   [% FOREACH item = row %]
      <td>[% item %]</td>
   [% END %]
   </tr>
[% END %]

A plugin can be referenced by an alternative name:

[% USE scores = table(myscores, cols=5) %]

[% FOREACH row = scores.rows %]
   ...
[% END %]

You can use this approach to create multiple plugin objects with different configurations. This example shows how the format plugin is used to create subroutines bound to variables for formatting text as per printf( ).

[% USE bold = format('<b>%s</b>') %]
[% USE ital = format('<i>%s</i>') %]

[% bold('This is bold')   %]
[% ital('This is italic') %]

The previous example generates the following output:

<b>This is bold</b>
<i>This is italic</i>

This next example shows how the URL plugin can be used to build dynamic URLs from a base part and optional query parameters:

[% USE mycgi = URL('/cgi-bin/foo.pl', debug=1) %]
<a href="[% mycgi %]">...
<a href="[% mycgi(mode='submit') %]"...

The previous example generates the following output:

<a href="/cgi-bin/foo.pl?debug=1">...
<a href="/cgi-bin/foo.pl?mode=submit&debug=1">...

The LOAD_PERL option (disabled by default) provides a further way by which external Perl modules may be loaded. If a regular Perl module (i.e., not a Template::Plugin::* or other module relative to some PLUGIN_BASE) supports an object-oriented interface and a new( ) constructor, it can be loaded and instantiated automatically. The following trivial example shows how the IO::File module might be used:

[% USE file = IO.File('/tmp/mydata') %]

[% WHILE (line = file.getline) %]
   <!-- [% line %] -->
[% END %]

Chapter 6 discusses plugins in excruciating detail.

Macros

Sometimes Template Toolkit code can get very complicated. You can often have complex pieces of code that get repeated a number of times throughout your template. One solution to this problem is to extract the code into another template and call it with PROCESS whenever it is needed:

[% PROCESS my/gnarly/code day='Monday' %]
...later...
[% PROCESS my/gnarly/code day='Tuesday' %]

This idea works well for larger chunks of code, but it can be a little unwieldy if used often. A far better idea is to define a macro. A macro is a piece of arbitrary Template Toolkit code that is given a name, enabling you to call it later in the template. For example:

[% USE date -%]
[% MACRO now GET date.format(date.now, '%H:%M:%S') -%]
[% MACRO today GET date.format(date.now, '%Y-%m-%d') -%]

This defines two macros called now and today that will output the current time and date whenever they are called in the template:

[% now %] [% today %]

The following subsection introduces the directive for working with macros.

MACRO

The MACRO directive allows you to define a directive or directive block that is evaluated each time the macro is called:

[% MACRO header INCLUDE header %]

Calling the macro as:

[% header %]

is then equivalent to:

[% INCLUDE header %]

Macros can be passed named parameters when called. These values remain local to the macro. Therefore, calling the macro as:

[% header(title='Hello World') %]

is equivalent to:

[% INCLUDE header title='Hello World' %]

A MACRO definition may include parameter names. Values passed to the macros are then mapped to these local variables. Other named parameters may follow these.

[% MACRO header(title) INCLUDE header %]

[% header('Hello World') %]
[% header('Hello World', bgcol='#123456') %]

There are equivalent to:

[% INCLUDE header title='Hello World' %]
[% INCLUDE header title='Hello World' bgcol='#123456' %]

Here’s another example, defining a macro for display numbers in comma-delimited groups of three, using the chunk and join virtual method:

[% MACRO number(n) GET n.chunk(-3).join(',') %]

[% number(1234567) %]    # 1,234,567

A MACRO may precede any directive, including block directives, but must conform to the structure of the directive:

[%  terms = {
        sass  = 'know, be aware of, meet, have sex with',
        hoopy = 'really together guy',
        frood = 'really, amazingly together guy'
    };

    MACRO explain(term) 
        IF (explanation = terms.$term);
            "$term ($explanation)";
        ELSE;
            term;
        END;
%]

Here we define the explain(term) macro as an IF / ELSE directive. It consults a hash table to locate an explanation for the term passed as an argument. It generates a string containing the term and explanation, or the term by itself if no explanation is found.

Hey you [% explain('sass') %] that
[% explain('hoopy') %] Ford Prefect?
There's a [% explain('frood') %] 
who really knows where his towel is.

This generates the following output:

Hey you sass (know, be aware of, meet, have sex with) that 
hoopy (really together guy) Ford Prefect?
There's a frood (really, amazingly together guy) 
who really knows where his towel is.

A MACRO can also be defined as an anonymous BLOCK. The block will be evaluated each time the macro is called.

[%  MACRO translate(text) 
      BLOCK;
        words = [ ];
        FOREACH word IN text.split;
          IF (explanation = terms.$word);
            words.push("$word ($explanation)");
          ELSE;
            words.push(word);
          END;
        END;
        words.join(' ');
      END
%]

This macro splits the text passed as an argument into words, attempts to explain them, and then joins them back up into a single piece of text:

[% translate(
     "Hey you sass that hoopy Ford Prefect?
      There's a frood who really knows where 
      his towel is."
   )
%]

This is the output generated by the previous template fragment:

Hey you sass (know, be aware of, meet, have sex with)
that hoopy (really together guy)
Ford Prefect? There's a frood (really, amazingly together guy)
who really knows where his towel is.

A MACRO can also be defined as a PERL block, but will require the EVAL_PERL option to be set:

[% MACRO triple(n) PERL %]
     my $n = $stash->get('n');
     print $n * 3;
[% END -%]

The PERL and RAWPERL directives are covered at the end of this chapter.

Template Metadata

The Template Toolkit compiles a template into a Perl object (an instance of the class Template::Document). This object contains Perl code that reproduces the required behavior of the template. You can access the data in this object via the template variable.

The Template::Document has access to various items of metadata about the template that you can access via template. This always includes the name of the template and the last modification time, so it is always possible to include things such as this in your template:

[% USE date(format => '%Y-%m-%d %H:%M:%S') %]
[% template.name %]
Last modified: [% date.format(template.modtime) %]

Further metadata items can be added using the META directive, discussed next. These new items will also be available through the template variable.

[% META moon_phase = 'first quarter' -%]
Phase of moon: [% template.moon_phase %]

META

The META directive allows simple metadata items to be defined within a template. These are evaluated when the template is parsed, and as such may contain only simple values (e.g., it’s not possible to interpolate other variable values into META variables).

[% META
   title   = 'The Cat in the Hat'
   author  = 'Dr. Seuss'
   version = 1.23 
%]

The template variable contains a reference to the main template being processed. These metadata items may be retrieved as attributes of the template.

<h1>[% template.title %]</h1>
<h2>[% template.author %]</h2>

The name and modtime metadata items are automatically defined for each template to contain its name and modification time in seconds since the epoch:

[% USE date %]                # use Date plugin to format time
...
[% template.name %] last modified
at [% date.format(template.modtime) %]

The PRE_PROCESS and POST_PROCESS options allow common headers and footers to be added to all templates. The template reference is correctly defined when these templates are processed, allowing headers and footers to reference metadata items from the main template:

$tt = Template->new({
    PRE_PROCESS  => 'header',
    POST_PROCESS => 'footer',
});

$tt->process('cat_in_hat');

header:

<html>
<head>
<title>[% template.title %]</title>
</head>
<body>

cat_in_hat:

[% META
   title   = 'The Cat in the Hat'
   author  = 'Dr. Seuss'
   version = 1.23 
   year    = 2000
%]

The cat in the hat sat on the mat.

footer:

<hr />
&copy; [% template.year %] [% template.author %]
</body>
</html>

The output generated from the preceeding example is:

<html>
<head>
<title>The Cat in the Hat</title>
</head>
<body>

The cat in the hat sat on the mat.

<hr />
&copy; 2000 Dr. Seuss
</body>
</html>

Exception Handling

No matter how careful you are, things always go wrong. Errors are a fact of life. Your templates could contain bad code and fail to compile. Or you could get an error thrown from the Template Toolkit—maybe it can’t find the header file you asked for. Or your back-end code could raise an error—you failed to connect to the required database. The Template Toolkit wouldn’t be of much use if common errors such as these caused it to keel over and die. That’s why it provides an exception-handling mechanism in the form of TRY...CATCH.

Exceptions are just a fancy way of saying errors. They’re structured as objects so that an error can have a type (just a word to identify the kind of error that occurred, such as database, user, or file) and an info field that provides further information about the specifics of the error. They get thrown just like regular errors, via Perl’s die, but rather than saying die 'bad apple', we say THROW bad apple.

You don’t have to explicitly add code to handle errors. If you don’t and an error occurs, it gets reported in the usual way. But if you know that errors might occur and you have a sensible way of recovering from them, it’s good to add TRY...CATCH to do that.

Using the exception mechanism doesn’t force you to worry about all errors that might occur. You can filter on the type of error and just look out for your one custom error code to catch, letting everything else pass through. Exceptions can also be nested, so you can catch them at the most appropriate level in your template.

TRY / THROW / CATCH / FINAL

The Template Toolkit supports fully functional, nested exception handling. The TRY directive introduces an exception-handling scope that continues until the matching END directive. Any errors that occur within that block will be caught and can be handled by one of the CATCH blocks defined.

[% TRY %]
   ...blah...blah...
   [% CALL somecode %]
   ...etc...
   [% INCLUDE someblock %]
   ...and so on...
[% CATCH %]
   An error occurred!
[% END %]

Errors are raised as exceptions (objects of the Template::Exception class) and contain two fields, type and info. The exception type can be any string containing letters, numbers, “_” or “.”, and is used to indicate the kind of error that occurred. The info field contains an error message indicating what actually went wrong. Within a CATCH block, the exception object is aliased to the error variable. You can access the type and info fields directly.

[% mydsn = 'dbi:MySQL:foobar' %]
...

[% TRY %]
   [% USE DBI(mydsn) %]
[% CATCH %]
   ERROR! Type: [% error.type %]
          Info: [% error.info %]
[% END %]

The previous example generates the following output (assuming a nonexistent database called foobar):

ERROR!  Type: DBI
        Info: Unknown database "foobar"

The error variable can also be specified by itself and will return a string of the form $type error - $info:

...
[% CATCH %]
ERROR: [% error %]
[% END %]

The previous example generates the following output:

ERROR: DBI error - Unknown database "foobar"

Each CATCH block may be specified with a particular exception type denoting the kind of error that it should catch. Multiple CATCH blocks can be provided to handle different types of exceptions that may be thrown in the TRY block. A CATCH block specified without any type, as in the previous example, is a default handler that will catch any otherwise uncaught exceptions. This also can be specified as [% CATCH DEFAULT %].

[% TRY %]
   [% INCLUDE myfile %]
   [% USE DBI(mydsn) %]
   [% CALL somecode %]
   ...
[% CATCH file %]
   File Error! [% error.info %]
[% CATCH DBI %]
   [% INCLUDE database/error.html %]
[% CATCH %]
   [% error %]
[% END %]

Remember that you can specify multiple directives within a single tag, each delimited by ;. Thus, you might prefer to write your simple CATCH blocks more succinctly as:

[% TRY %]
   ...
[% CATCH file; "File Error! $error.info" %]
[% CATCH DBI;  INCLUDE database/error.html %]
[% CATCH; error %]
[% END %]

or even:

[% TRY %]
   ...
[% CATCH file ;
       "File Error! $error.info" ;
   CATCH DBI ;
       INCLUDE database/error.html ;
   CATCH ;
       error ;
   END
%]

The DBI plugin throws exceptions of the DBI type (in case that wasn’t already obvious). The other specific exception caught here is of the file type.

A file error is automatically thrown by the Template Toolkit when it can’t find a file, or fails to load, parse, or process a file that has been requested by an INCLUDE, PROCESS, INSERT, or WRAPPER directive. If myfile can’t be found in the previous example, the [% INCLUDE myfile %] directive will raise a file exception, which is then caught by the [% CATCH file %] block, generating the output:

File Error! myfile: not found

Note that the DEFAULT option (disabled by default) allows you to specify a default file to be used any time a template file can’t be found. This will prevent file exceptions from ever being raised when a nonexistent file is requested (unless, of course, the DEFAULT file doesn’t exist). Errors encountered once the file has been found (i.e., read error, parse error) will be raised as file exceptions as per usual.

Uncaught exceptions (i.e., the TRY block doesn’t have a type-specific or default CATCH handler) may be caught by enclosing TRY blocks that can be nested indefinitely across multiple templates. If the error isn’t caught at any level, processing will stop and the Template process( ) method will return a false value to the caller. The relevant Template::Exception object can be retrieved by calling the error( ) method.

[% TRY %]
   ...
   [% TRY %]
      [% INCLUDE $user.header %]
   [% CATCH file %]
      [% INCLUDE header %]
   [% END %]
   ...
[% CATCH DBI %]
   [% INCLUDE database/error.html %]
[% END %]

In this example, the inner TRY block is used to ensure that the first INCLUDE directive works as expected. We’re using a variable to provide the name of the template we want to include, user.header, and it’s possible this contains the name of a nonexistent template, or perhaps one containing invalid template directives. If the INCLUDE fails with a file error, we CATCH it in the inner block and INCLUDE the default header file instead. Any DBI errors that occur within the scope of the outer TRY block will be caught in the relevant CATCH block, causing the database/error.html template to be processed. Note that included templates inherit all currently defined template variables, so these error files can quite happily access the error variable to retrieve information about the currently caught exception. For example:

database/error.html:

<h2>Database Error</h2>
A database error has occurred: [% error.info %]

You can also specify a FINAL block. This is always processed regardless of the outcome of the TRY and/or CATCH block. If an exception is uncaught, the FINAL block is processed before jumping to the enclosing block or returning to the caller.

[% TRY %]
   ...
[% CATCH this %] 
   ...
[% CATCH that %] 
   ...
[% FINAL %]
   All done!
[% END %]

The output from the TRY block is left intact up to the point where an exception occurs. For example, this template:

[% TRY %]
   This gets printed 
   [% THROW food 'carrots' %]
   This doesn't
[% CATCH food %]
   culinary delights: [% error.info %]
[% END %]

generates the following output:

This gets printed
culinary delights: carrots

The CLEAR directive can be used in a CATCH or FINAL block to clear any output created in the TRY block. For example, this template:

[% TRY %]
   This gets printed 
   [% THROW food 'carrots' %]
   This doesn't
[% CATCH food %]
   [% CLEAR %]
   culinary delights: [% error.info %]
[% END %]

generates the following output:

culinary delights: carrots

Exception types are hierarchical, with each level being separated by the familiar dot operator. A DBI.connect exception is a more specific kind of DBI error. Similarly, a myown.error.barf is a more specific kind of myown.error type, which itself is also a myown error. A CATCH handler that specifies a general exception type (such as DBI or myown.error) will also catch more specific types that have the same prefix as long as a more specific handler isn’t defined. Note that the order in which CATCH handlers are defined is irrelevant; a more specific handler will always catch an exception in preference to a more generic or default one.

[% TRY %]
   ...
[% CATCH DBI ;
     INCLUDE database/error.html ;
   CATCH DBI.connect ;
     INCLUDE database/connect.html ;
   CATCH ; 
     INCLUDE error.html ;
   END
%]

In this example, a DBI.connect error has its own handler, a more general DBI block is used for all other DBI or DBI.* errors, and a default handler catches everything else.

Exceptions can be raised in a template using the THROW directive. The first parameter is the exception type, which doesn’t need to be quoted (but can be, it’s the same as INCLUDE), followed by the relevant error message, which can be any regular value such as a quoted string, variable, etc.

[% THROW food "Missing ingredients: $recipe.error" %]

[% THROW user.login 'no user id: please login' %]

[% THROW $myerror.type "My Error: $myerror.info" %]

It’s also possible to specify additional positional or named parameters to the THROW directive if you want to pass more than just a simple message back as the error info field:

[% THROW food 'eggs' 'flour' msg='Missing Ingredients' %]

In this case, the error info field will be a hash array containing the named arguments—in this case msg => 'Missing Ingredients'—and an args item that contains a list of the positional arguments—in this case eggs and flour. The error type field remains unchanged; here it is set to food.

[% CATCH food %]
   [% error.info.msg %]
   [% FOREACH item = error.info.args %]
      * [% item %]
   [% END %]
[% END %]

This produces the output:

Missing Ingredients
  * eggs
  * flour

In addition to specifying individual positional arguments as [% error.info.args.n %], the info hash contains keys directly pointing to the positional arguments, as a convenient shortcut:

[% error.info.0 %]   # same as [% error.info.args.0 %]

Exceptions can also be thrown from Perl code that you’ve bound to template variables, or defined as a plugin or other extension. To raise an exception, call die( ) passing a reference to a Template::Exception object as the argument. This will then be caught by any enclosing TRY blocks from where the code was called.

use Template::Exception;
...

my $vars = {
    foo => sub {
        # ... do something ...
        die Template::Exception->new('myerr.naughty',
                                     'Bad, bad error');
    },
};

Therefore, this template:

[% TRY %]
   ...
   [% foo %]
   ...   
[% CATCH myerr ;
     "Error: $error" ;
   END
%]

produces the following output:

Error: myerr.naughty error - Bad, bad error

The info field can also be a reference to another object or data structure, if required:

die Template::Exception->new('myerror', { 
    module => 'foo.pl', 
    errors => [ 'bad permissions', 'naughty boy' ],
});

Later, it can be used in a template:

[% TRY %]
   ...
[% CATCH myerror %]
   [% error.info.errors.size or 'no';
      error.info.errors.size =  = 1 ? ' error' : ' errors' -%]
   in [% error.info.module %]: 
      [% error.info.errors.join(', ') %].
[% END %]

generating the output:

2 errors in foo.pl:
   bad permissions, naughty boy.

You can also call die( ) with a single string, as is common in much existing Perl code. This will automatically be converted to an exception of the undef type (that’s the literal string `undef', not the undefined value). If the string isn’t terminated with a newline, Perl will append the familiar at $file line $line message.

sub foo {
    # ... do something ...
    die "I'm sorry, Dave, I can't do that\n";
}

If you’re writing a plugin, or some extension code that has the current Template::Context in scope (you can safely skip this section if this means nothing to you), you can also raise an exception by calling the context throw( ) method. You can pass it a Template::Exception object reference, a pair of ($type, $info) parameters, or just a $info string to create an exception of undef type.

$context->throw($e);            # exception object
$context->throw('Denied');      # 'undef' type
$context->throw('user.passwd', 'Bad Password');

CLEAR

The CLEAR directive can be used to clear the output buffer for the current enclosing block. It is most commonly used to clear the output generated from a TRY block up to the point where the error occurred.

[% TRY %]
   blah blah blah            # this is normally left intact
   [% THROW some 'error' %]  # up to the point of error
   ...
[% CATCH %]
   [% CLEAR %]               # clear the TRY output
   [% error %]               # print error string
[% END %]

Flow Control

Flow control is about making unexpected changes to the execution order of a template. This can be as simple as ending a FOREACH loop early, or as significant as ending the entire template processing process. These are generally exceptional cases, so you probably won’t need to use flow-control directives that often, but we discuss them here just in case.

RETURN

The RETURN directive can be used to stop processing the current template and return to the template from which it was called, resuming processing at the point immediately after the INCLUDE, PROCESS, or WRAPPER directive. If there is no enclosing template, the Template process( ) method will return to the calling code with a true value.

Before
[% INCLUDE half_wit %]
After

[% BLOCK half_wit %]
This is just half...
[% RETURN %]
...a complete block
[% END %]

The previous example produces the following output:

Before
This is just half...
After

STOP

The STOP directive can be used to indicate that the processor should stop gracefully without processing any more of the template document. This is a planned stop, and the Template process( ) method will return a true value to the caller. This indicates that the template was processed successfully according to the directives within it.

[% IF something.terrible.happened %]
   [% INCLUDE fatal/error.html %]
   [% STOP %]
[% END %]

[% TRY %]
   [% USE DBI(mydsn) %]
   ...
[% CATCH DBI.connect %]
   <p>Cannot connect to the database: [% error.info %]</p>
   <br>
   We apologize for the inconvenience.  The cleaning lady 
   has removed the server power to plug in her vacuum cleaner.
   Please try again later.
   </p>
   [% INCLUDE footer %]
   [% STOP %]
[% END %]

NEXT

The NEXT directive can be used to start the next iteration of a FOREACH or WHILE loop:

[% FOREACH user = userlist %]
   [% NEXT IF user.isguest %]
   Name: [% user.name %]    Email: [% user.email %]
[% END %]

LAST

The LAST directive can be used to prematurely exit a FOREACH or WHILE loop:

[% FOREACH user = userlist %]
   Name: [% user.name %]    Email: [% user.email %]
   [% LAST IF some.condition %]
[% END %]

BREAK can also be used as an alias for LAST.

Debugging

It’s possible that you won’t get everything just right in your templates the first time you write them. If you have problems working out what exactly is going on as the Template Toolkit is processing your template, the DEBUG directive can help you.

The DEBUG directive enables and disables directive debug messages within a template. It is used with an on or off parameter to enable or disable directive debugging messages from that point forward. When enabled, the output of each directive in the generated output will be prefixed by a comment indicating the file, line, and original directive text.

[% DEBUG on %]
directive debugging is on (assuming DEBUG option is set to true)
[% DEBUG off %]
directive debugging is off

The format parameter can be used to change the format of the debugging message:

[% DEBUG format '<!-- $file line $line : [% $text %] -->' %]

The DEBUG configuration option must be set to include DEBUG_DIRS for the DEBUG directives to have any effect. If DEBUG_DIRS is not set, the parser will automatically ignore and remove any DEBUG directives.

Perl Blocks

The Template Toolkit directives that we have seen up to now together define a presentation language that allows you to do just about anything you need to in order to control the display of your data. This is in keeping with the Template Toolkit philosophy of separating processing from presentation.

However, there may be times when you want to go beyond what Template Toolkit offers you. Very occasionally you might need the power of a full programming language within your templates. When nothing else will do, the Template Toolkit also gives you the option of embedding Perl directly in your templates in PERL and RAWPERL directive blocks.

Using PERL and RAWPERL blocks isn’t something that is widely encouraged because it tends to make templates messy and hard to read. It also leads to a poor separation of concerns when you mix application code with presentation templates. However, the Template Toolkit doesn’t enforce this separation, so you can embed Perl code inside your templates if you really want to. Because we don’t encourage it, this feature is disabled by default. You will have to enable the EVAL_PERL configuration option to embed Perl code.

PERL

The PERL directive allows you to embed a block of Perl code in a template. It looks like this:

[% PERL %]
   print "Hello world\n"
[% END %]

The EVAL_PERL configuration option must be enabled in order to use PERL blocks. If you try to use a PERL block when EVAL_PERL is disabled, a perl exception will be thrown with the message `EVAL_PERL not set’:

my $template = Template->new({
     EVAL_PERL => 1,
});

The Template Toolkit evaluates Perl code in the Template::Perl package. A number of special variables are predefined, providing access to various Template Toolkit objects.

The $context package variable contains a reference to the current Template::Context object. This can be used to access the functionality of the Template Toolkit to process other templates, and load plugins, filters, etc.:

[% PERL %]
   print $context->include('myfile');
[% END %]

The $stash variable contains a reference to the top-level stash object, which manages template variables. Through this, variable values can be retrieved and updated.

[% PERL %]
   $stash->set(foo => 'bar');
   print "foo value: ", $stash->get('foo');
[% END %]

The previous example generates the following output:

foo value: bar

Output is generated from the PERL block by calling print. Before evaluating the code, a filehandle called Template::Perl::PERLOUT is set up and selected as the default output filehandle. This will be connected to whatever output device was defined in the call to process. Your code should use this filehandle instead of STDOUT.

[% PERL %]
   print "foo\n";                           # OK
   print PERLOUT "bar\n";                   # OK, same as above
   print Template::Perl::PERLOUT "baz\n";   # OK, same as above
   print STDOUT "qux\n";                    # WRONG!
[% END %]

The PERL block may contain other template directives. These are processed before the Perl code is evaluated.

[% name = 'Fred Smith' %]

[% PERL %]
   print "[% name %]\n";
[% END %]

Thus, the Perl code in the previous example is evaluated as:

print "Fred Smith\n";

Exceptions may be thrown from within PERL blocks via die, and will be correctly caught by enclosing TRY blocks:

[% TRY %]
   [% PERL %]
      die "nothing to live for\n";
   [% END %]
[% CATCH %]
   error: [% error.info %]
[% END %]

The previous example generates the following output:

error: nothing to live for

RAWPERL

The Template Toolkit parser reads a source template and generates the text of a Perl subroutine as output. It then uses eval( ) to evaluate it into a subroutine reference. This subroutine is then called to process the template, passing a reference to the current Template::Context object through which the functionality of the Template Toolkit can be accessed. The subroutine reference can be cached, allowing the template to be processed repeatedly without requiring any further parsing.

For example, a template such as:

[% PROCESS header %]
The [% animal %] sat on the [% location %]
[% PROCESS footer %]

is converted into the following Perl subroutine definition:

sub {
    my $context = shift;
    my $stash   = $context->stash;
    my $output  = '';
    my $error;

    eval { BLOCK: {
        $output .=  $context->process('header');
        $output .=  "The ";
        $output .=  $stash->get('animal');
        $output .=  " sat on the ";
        $output .=  $stash->get('location');
        $output .=  $context->process('footer');
        $output .=  "\n";
    } };
    if ($@) {
        $error = $context->catch($@, \$output);
        die $error unless $error->type eq 'return';
    }

    return $output;
}

To examine the Perl code generated, such as in the previous example, set the $Template::Parser::DEBUG package variable to any true value. You can also set the $Template::Directive::PRETTY variable to true to have the code formatted in a readable manner for human consumption. The source code for each generated template subroutine will be printed to STDERR on compilation (i.e., the first time a template is used).

$Template::Parser::DEBUG = 1;
$Template::Directive::PRETTY = 1;

...

$tt->process($file, $vars)
    || die $tt->error( ), "\n";

The PERL ... END construct allows Perl code to be embedded into a template (when the EVAL_PERL option is set), but it is evaluated at “runtime” using eval( ) each time the template subroutine is called. This is inherently flexible but not as efficient as it could be, especially in a persistent server environment where a template may be processed many times.

The RAWPERL directive allows you to write Perl code that is integrated directly into the generated Perl subroutine text. It is evaluated once at compile time and is stored in cached form as part of the compiled template subroutine. This makes RAWPERL blocks more efficient than PERL blocks.

The downside is that you must code much closer to the metal. Within PERL blocks, you can call print( ) to generate some output. RAWPERL blocks don’t afford such luxury. The code is inserted directly into the generated subroutine text and should conform to the convention of appending to the $output variable.

[% PROCESS  header %]

[% RAWPERL %]
   $output .= "Some output\n";
   ...
   $output .= "Some more output\n";
[% END %]

The critical section of the generated subroutine for this example would then look something like this:

...
eval { BLOCK: {
    $output .=  $context->process('header');
    $output .=  "\n";
    $output .= "Some output\n";
    ...
    $output .= "Some more output\n";
    $output .=  "\n";
} };
...

As with PERL blocks, the $context and $stash references are predefined and available for use within RAWPERL code.

Only very advanced Template Toolkit users will ever need to use a RAWPERL block.



[7] Larry has since changed his mind and it looks as if the ~ will be the Perl 6 string concat operator. As always, this is all subject to change.

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