Perl Programming Page 11 - Building a Complete Website using the Template Toolkit |
Most real web sites will require far more complex layout templates than the simple wrapper we saw in Example 2-16. A common practice is to use HTML tables to place different elements such as headers, footers, and menus in a consistent position and formatting style. These elements may themselves be built using tables and other HTML elements, perhaps nested several times over. This can quickly lead to confus ing markup that is hard to read and even harder to update. Consider the following example, which illustrates how difficult nested tables can be to write and maintain: <table border="0" cellpadding="0" cellspacing="0"> The sensible formatting helps to make the structure clearer through use of indenting. However, it is still difficult to match rows and cells with their correspondingn tables, and there is little indication of what the different tables contribute to the overall layout. A better approach is to build the layout using several different templates. For example, we can simplify the preceding template by moving the inner tables to separate <table border="0" cellpadding="0" cellspacing="0"> Now we can easily see the high-level structure without getting bogged down in the detail of the nested tables. Furthermore, by giving our templates names that reflect their purpose (e.g., sidebar and topmenu), we effectively have a self-documenting template that shows at a glance what it does. Another benefit is that the individual elements, the sidebar and topmenu in this example, will themselves be much easier to write and maintain in isolation. They also become reusable, allowing you to incorporate them into another part of the site (or perhaps another site) with a PROCESS or similar directive. Layout Example Let’s work through a complete example now, applying this principle to the presentation framework for our web site. Example 2-17 shows an alternate version of the wrapper template that delegates the task to two further templates, html and layout. Example 2-17. lib/wrapper2 [% WRAPPER html + layout; The two wrapper templates, html and layout, are both specified in the one WRAPPER directive, separated using the + character in the same way that we used it with the PROCESS directive in Example 2-9. In this case, the page content will be processed first, then the layout template, and finally the html template. Remember that the If we unwrap the preceding directive into two separate WRAPPER calls, it should become more obvious why the WRAPPER directive processes the templates in the reverse order to how they’re specified: [% WRAPPER html; The end result is that it does what you would expect, regardless of the slightly counterintuitive order in which it does it. The html template ends up wrapping the layout template, which in turn wraps the value of the content variable, which in this case is the output from processing the main page template. Side-effect wrappers The WRAPPER directive can also be used in side-effect notation. Consider the following fragment: [% WRAPPER layout; You can simplify this by writing it as follows: [% content WRAPPER layout %] The wrapper template shown in Example 2-17 can be rewritten in the same way, as shown in Example 2-18.
[% content WRAPPER html + layout -%] Separating layout concerns Using two separate layout templates, html and layout, allows us to make a clear separation between the different kinds of markup that we’re adding to each page. The html template adds the <head> and <body> elements required to make each page valid HTML. The layout template deals with the overall presentation of the visible page Example 2-19 shows the html template. Example 2-19. lib/html <html> <body bgcolor="[% bgcol %]"> Example 2-20 shows the layout template. Example 2-20. lib/layout <table border="0" width="100%"> We’ve created a new header template, pagehead, shown in Example 2-21, which generates a headline for the page. It’s simple for now, but we can easily change it to something more complicated at a later date. Example 2-21. lib/pagehead [% template.title %] We’re also using another template, menu, to handle the generation of a menu for the site. We’ll be looking at this shortly. Example 2-22 shows the final template used in the layout, pageinfo. This incorporates the copyright message and some information about the page template being processed. Example 2-22. lib/pageinfo [% USE Date %] © [% copyr %] <br /> [% template.name -% ] Notice how we’re using the template.name and template.modtime variables to access the filename and modification time of the current page template. The template.modtime value is returned as a large number that means something to computers* but not a great deal to humans. To turn this into something more meaningful, we’re using the Date plugin to format the number as a human-readable string. Plugins and the USE directive Plugins are a powerful feature of the Template Toolkit that allow you to load and use complex functionality in your templates, but without having to worry about any of the underlying implementation detail. Plugins are covered in detail in Chapter 6, but there’s not much you need to know to start using them. In Example 2-22, we first load the Date plugin with the USE directive: [% USE Date %] This creates a Date template variable that contains a reference to a plugin object (of the Template::Plugin::Date class, but you don’t need to know that). We can then call the format method against the Date object using the dot operator, passing the value for template.modtime as an argument: [%- Date.format(template.modtime) %] The output generated would look something like this: 17:43:35 14-Jul-2003 * It’s the number of seconds that have elapsed since January 1, 1970, known as the the Unix epoch. That’s all we need to do to load and use the Date plugin. Dozens of plugins are avail able for doing all kinds of different tasks, described in detail in Chapter 6.
|
|
|
|
|
|
|
|