Perl Programming Page 12 - Building a Complete Website using the Template Toolkit |
In the layout template in Example 2-20, we delegate the task of generating a menu for the web site to the menu template. Before we look at how the template does this, let’s see an example of the kind of HTML that we would like it to generate. <table border="0"> The entire menu is defined as a <table> element, containing one <tr> row for each item, each of which holds two <td> cells, one to display an icon, the other a link to a particular page. Only two items are in this simple example, but already we can see how it gets repetitive very quickly. This suggests that we can modularize the markup into separate template components. Simple Menu Template Example 2-23 shows a menu template that defines the outer <table> elements and uses a second template, menuitem, to generate each item. Example 2-23. lib/menu <table border="0"> PROCESS menuitem [% BLOCK menuitem %] The menuitem template block is defined at the bottom of the menu template, but that doesn’t stop us from using it earlier in the same template, before it is defined. The menuitem block will remain defined while the menu template is being processed. Any other templates that are called from within the menu template (e.g., by a PROCESS or INCLUDE directive) will also be able to use the menuitem block. Component Libraries When a template is loaded using the PROCESS directive, any BLOCK definitions within it will be imported and available for use in the calling template. Templates loaded using the INCLUDE directive keep to themselves and don’t export their BLOCK definitions (or any of their local variables, as described in the earlier discussion of the This feature allows you to create single template files that contain libraries of smaller template components, defined using the BLOCK directive. This is illustrated in Example 2-24. Example 2-24. lib/mylib [% BLOCK image -%] Notice how the icon BLOCK definition is defined within a single directive, and consists of nothing more than a call to the image template component, defined earlier in the same file. This illustrates how easy it is to reuse existing components to quickly adapt them for more specific, or alternate purposes. The BLOCK definitions can be loaded from the mylib template with a PROCESS directive. Then they can be used just like any other template component. Example 2-25 shows a variation of the menu template from Example 2-23 in which the icon and Example 2-24. lib/mylib [% BLOCK image -%] [% BLOCK link -%] [% BLOCK icon; Example 2-25. lib/menu2 [% PROCESS mylib %] <table border="0"> PROCESS menuitem [% BLOCK menuitem %] The EXPOSE_BLOCKS option You can also set an option that allows you to use BLOCK directives without having to first PROCESS the template in which they’re defined. The expose_blocks option for ttree and the corresponding EXPOSE_BLOCKS option for the Template module can be set to make this possible. For example, by adding the following to the etc/ttree.cfg file: expose_blocks we can then access a BLOCK in the mylib template like so: [% PROCESS mylib/icon %] The template name, mylib, is followed by the BLOCK name, icon, separated by a / (slash) character. The notation is intentionally identical to how you would specify the icon file in the mylib directory. This is another example of how the Template Toolkit abstracts certain underlying implementation details so that you don’t tie yourself down to one particular way of doing something. At a later date, for example, you might decide to split the mylib template into sepa rate files, stored in the mylib directory. The same directive will continue to work because the syntax is exactly the same for blocks in files as it is for files in directories: [% PROCESS mylib/icon %] This gives you more flexibility in allowing you to change the way you organize your template components, without having to worry about how that might affect the templates that use them. The FOREACH Directive The menu component from Example 2-25 can be simplified further by first defining a list of menu items and then iterating over them using the FOREACH directive. Example 2-26 demonstrates this. Example 2-26. lib/menu3 [% PROCESS mylib %] [% menu = [ <table border="0"> The menu variable is defined as a list of hash arrays, each containing a text and link item: [% menu = [ The main body of the template defines an HTML <table> element. Within the table, the FOREACH directive iterates through the menu list, setting the item variable to each element in turn. <table border="0"> The block following the FOREACH directive, up to the corresponding END, can contain text and other directives, even including nested FOREACH blocks. To make the code easier to read, we might prefer to define the menuitem BLOCK , as shown in Example 2-25. This allows us to simplify the FOREACH directive, merging it into a single tag. The FOREACH block now contains just one directive to PROCESS the menuitem component. The text and link variables are set to the item.text and item.link values, respectively. <table border="0"> When the items in a FOREACH list are hash arrays, as they are in Example 2-26, you can omit the name of the item variable: <table border="0"> In this case, the values in each hash array will be made available as local variables inside the FOREACH block. So item.text becomes the text variable, and item.link becomes link, but only within the scope of the FOREACH block. This conveniently allows us to process the menuitem template without needing to explicitly derefer ence the item variables. There’s one more improvement we can make by taking advantage of the Template Toolkit’s side-effect notation. Instead of writing the PROCESS menuitem directive in the FOREACH block all by itself, we can put it before the FOREACH and do away with the semicolons and END keyword: <table border="0"> All these enhancements to the menu template are shown in Example 2-27. Example 2-27. lib/menu4 [% PROCESS mylib %] <table border="0"> [% BLOCK menuitem %] Defining and Using Complex Data The variables that we have used so far have mostly been simple scalar variables that contain just one value. The few exceptions include the tantalizing glimpses of the template variable, and the Date plugin in Example 2-22. As we saw in Chapter 1, the Template Toolkit also supports lists and hash arrays for complex data, and allows you to access Perl subroutines and objects. In this section, we will look more closely at defining and using complex data struc tures, and describe the different Template Toolkit directives for inspecting, presenting, and manipulating them.
|
|
|
|
|
|
|
|