When you define a reusable template component, you may want to provide default values for any variables used in the template. For example, the following template component might want to ensure that sensible values are provided for the <title> element and bgcolor attribute in the <body>, even if the respective title and bgcol
The DEFAULT directive
One way to achieve this is by using the DEFAULT directive. The syntax is the same as SET in everything but the keyword, allowing you to provide default values for one or more variables:
The key difference between DEFAULT and SET is that DEFAULT will set the variable to the value prescribed only if it is currently undefined, if it is set to an empty string, or if it contains the number zero. (Perl programmers will recognize the similarity with Perl’s idea about what is true and false when it comes to the value of a variable.) The com ponent will use any existing values for title and bgcol , either defined globally or passed as explicit arguments when the template is used. Otherwise, it will use the values provided in the DEFAULT directive.
Another approach is to use Template Toolkit expressions instead of just variables. Expressions allow you to make logical statements including the and and or operators, both of which can be written in either upper-or lowercase. For example, we can write:
[% bgcol or '#FF6600' %]
instead of just:
[% bgcol %]
The tertiary ?: operator is another option. It provides the equivalent of an IF... THEN...ELSE construct, in which the expression to the left of the ? is evaluated to determine whether it is true or false. If true, whatever comes after the ? and before the : is used. Otherwise, it returns whatever follows the :.
Here’s an example showing how the ?: operator can be used to generate an appropriate title for the page:
[% title ? "Arthur Dent: $title"
If the title variable is set, the string "Arthur Dent: $title" is used. This uses vari able interpolation to insert the current value for the title variable into the string, following Arthur’s name. If title isn’t set to anything that the Template Toolkit considers meaningfully true, the string "Arthur Dent's Web Site" is instead used. The expression doesn’t need to be split across two lines as we’ve shown here, but in this case it helps to make the code clearer and easier to read.
So if title is set to Earth , the directive will generate the following output:
Arthur Dent: Earth
If the title isn’t set, it will instead generate this output:
Arthur Dent's Web Site
Expressions can also contain comparison operators, as shown in the following example. These are discussed in detail in Chapter 3.
[% age > 18 ? 'Welcome to my site...'
= versus = =. One important distinction worth mentioning now is the difference between = and == . The first performs an assignment, setting the variable named on the left to the value (or expression) on the right:
[% foo = bar %]
The second is the equality comparison operator, which tests to see whether the string values of the items on either side are identical:
[% foo == bar ? 'equal' : 'not equal' %]
Setting variables using expressions. Expressions can also be used to set the value of a variable. For example, the pagetitle variable can be set to either of the values previously shown, depending on the setting of title, using the following code:
[% pagetitle = title ? "Arthur Dent: $title"
It’s perfectly valid to use a variable in an expression to update the same variable. Everything to the right of the = is evaluated first, and the resulting value is then used to set the variable specified to the left of the = :
[% title = title ? "Arthur Dent: $title"
Setting variables using directives. You can also assign the output of a directive to a vari able. In the following example, the header template is processed using the PROCESS directive and the generated output is stored in the headtext variable:
[% headtext = PROCESS header %]
The IF Directive
The IF directive can be used to encode more complex conditional logic in templates. It evaluates the expression following the IF keyword, which in these examples will be a simple variable. If the expression is true, the following block, up to the matching END directive, is processed. Otherwise, it is ignored.
Here’s a simple example:
This example uses an IF block to add the bgcolor attribute to the HTML element, but only if the bgcol variable is defined and contains a true value. By careful placement of - characters at the start and end of the IF and END directives, we’re enabling the Template Toolkit’s prechomping and postchomping facility. This removes the newline characters before the [% tags and after the %] tags so that the output lines up in the correct place in the <body> element.
So, for a bgcol value of #FF6600, the following output would be generated:
For an undefined bgcol, we would instead see the following:
Like many of the Template Toolkit directives that expect a block to follow, the IF directive can be used in side-effect notation.
For example, you can write:
[% INCLUDE header IF title %]
instead of the more laborious:
[% IF title; INCLUDE header; END %]
This works only when you’ve got a single directive or variable as the content for the block—in this example, it’s the INCLUDE header directive. Our earlier example, which constructed the tag, included both text and a reference to the bgcol variable in the block. However, we can write this using a double-quoted string to interpolate the value for bgcol:
<body [%- " bgcolor=\"$bgcol"" IF bgcol %]>
Matters are complicated a little by the need to escape the double quotes inside the double quotes. The \ character tells the Template Toolkit that the following " is part of the string, and not the quote that terminates it. Overall it’s an improvement over the more explicit IF...END form and illustrates a useful principle.
You can add an ELSE block after the IF block, which will be processed if the variable (or more generally, the expression) is false. For example:
[% IF bgcol -% ]
There is also the ELSIF directive, which allows you to define different blocks for different conditions:
[% IF name == 'Arthur Dent'
In this example, the ELSIF expression uses the match virtual method to test whether the name contains anything looking remotely Vogon. The argument passed to the match method is a Perl regular expression, allowing us to use the (?i:...) grouping to construct a case-insensitive match. An ELSE block is also provided in case neither the IF nor ELSIF conditions match.
The SWITCH directive, described in detail in Chapter 4, provides an alternative for more complicated multiway matching.