Developer

Dynamic Web templates with dTemplate

Learn to use dTemplate, a Perl-based Web template engine that separates the layout HTML from the logic code.

Scripting languages such as PHP and Perl make it very easy to create dynamic Web pages by placing program code inside HTML markup. This code does the dirty work—connecting to a database, processing user input, performing calculations—and produces output which then integrates neatly with the rest of the page. The only problem: Your code ends up looking like a bowl of spaghetti, because the HTML markup and scripting functions are so closely intertwined with each other.

It's precisely this reason that causes many developers to look for more efficient ways of structuring their dynamic Web pages. In this more efficient world, HTML markup or layout code is separated from the business logic or functions that drive the page. This means that Web designers can work on "how a page looks" independent of Web developers, who only need to focus on "how the page works." For content-heavy sites that receive data from a variety of sources—XML, RDF, RSS, MySQL—a further degree of separation can be introduced through a content layer, which takes care of "what the page contains."

In this article, I'll introduce you to this more efficient way of structuring Web pages with dTemplate, a Perl-based template engine. You'll learn the basics, starting with how to separate page layout from business logic, and ending with how to integrate multiple templates to generate a single page.

How a template engine works

An important component of the tiered approach to Web development is a "template engine," which allows a designer to create page templates for the user interface. These templates typically contain no data at all; instead, they contain placeholders for data, which are automatically replaced with content at run-time by the template engine. The retrieval of the content from one or more data sources, as well as any specific scripting functionality required by the page, is created independently from the layout template.

The template engine thus takes care of integrating the layout with the business logic and presenting a composite result when the page is requested by a user. This separation between layout and content makes it possible for designers and developers to work on the same page simultaneously, without interfering with or overlapping each other's scope of responsibility.

A number of template engines exist for both PHP and Perl. The one I'm using for this tutorial is called dTemplate, and it's fast, stable, and fairly full-featured (three important attributes you should always look for in a template system).

dTemplate is licensed under the GPL and is maintained by Balázs Szabó. It is written in Perl with a C extension and can be downloaded from CPAN. Detailed installation instructions are provided in the download archive, but the simplest way to install it is to use the CPAN shell, as follows:

shell> perl -MCPAN -e shell
cpan> install dTemplate

If you use the CPAN shell, dependencies will be automatically downloaded for you (unless you told the shell not to download dependent modules). If you choose to manually download and install dTemplate, the installation procedure is the standard make-install routine, as follows (this tutorial uses version 2.4 of dTemplate):

shell> tar -xzvf dTemplate-2.4.tar.gz
shell> cd dTemplate-2.4
shell> perl Makefile.PL
shell> make
shell> make install

Creating a simple template

Once you have dTemplate installed and configured, begin by creating a subdirectory under your Web server document root called templates/ and placing the file color.tmpl inside it. Here is what goes inside color.tmpl:

<html><head></head>
<body>

<h2>My favorite color is $FAVCOLOR$</h2>

</body>
</html>

This is fundamentally what every template looks like—a regular HTML page that contains layout code but no actual data. The data is represented by one or more template variables, which are enclosed in $ symbols. In the example above, $FAVCOLOR$ is a template variable that will be replaced with an actual value by the template engine.

So now let's look at the script that will utilize this template.

Parsing a template and replacing template variables


The simple template we created earlier is only half the puzzle. The other half is a CGI script in Listing A called color.cgi, which must be placed inside your server's CGI-BIN directory.

This script takes care of reading the template file into the dTemplate engine and replacing the variable placeholder inside it with an actual value. There are three basic steps:

  1. The new() method accepts a hash whose "file" key points to the template file and creates a $tmpl object to represent the template.
  2. The parse() method of our newly-minted $tmpl object accepts a hash of key-value pairs (where the keys correspond to the template placeholders, and the values represent the content that will replace them) and performs variable interpolation on the template by replacing the $FAVCOLOR$ placeholder with the value "indigo".
  3. The return value of parse() is stored in the $output variable and printed to the browser after the mandatory "Content-Type" header.

Listing B shows what users will see when they navigate to http://server/cgi-bin/color.cgi.

Again, any dTemplate requires at least two components: a Perl script with the business logic and one or more template files containing the layout.

The advantages of separating layout and code

Splitting a Web page in this manner has two important advantages. First, it physically separates the HTML layout from server-side code, allowing developers to work on their portion of a page independently from the designers. This separation means a designer can also update the way a page looks without touching the server-side code. Yes, the designer does need to reuse the correct variable placeholders in their new locations. But it's much easier to relocate simple variable placeholders than to navigate complex Perl or PHP code blocks looking for the snippets of HTML buried within.

Second, because the page template is stored in a separate file, the same template may be called from different scripts. This makes it possible to easily reuse components of the user interface—menus, buttons, tables, headers and footers—potentially reducing repetition and redundancies.

Using multiple templates in a single page

Using a template engine gives you the ability to abstract common page elements into separate files and import them into your pages when needed (and with different data each time, if that's what you want). To do this, you must first break up your Web page into separate files or "mini-templates," and then create dTemplate objects for each template. You can then parse() each template, perform variable interpolation as needed, and append the result of each parse() run to previously generated output to create a composite page.

It's easier in practice than it sounds. To illustrate, let's assume you have a page containing three sections: the header, footer, and body. Break up these sections into three separate template files called header.tmpl (Listing C), body.tmpl (Listing D), and footer.tmpl (Listing E).

Now, what you need is a script to read and parse each template, and generate a single page using all three of them. See Listing F for an example.

Since this script has to deal with three templates, and thus three dTemplate objects to be created and referenced, I've used a slightly different technique. I've first created a Perl hash to store the names of the template files, as well as a convenient short name for each, and then used a loop to create dTemplate objects for each file. These dTemplate objects are accessible using the syntax $template->{shortname}, which makes it easy to access individual methods of each.

Once the dTemplate objects are created, it's a simple matter to parse() each one and replace the variables inside it with actual content. The output of each parse() run is appended to the output of the previous run, thereby incrementally building the Web page. The end result will look something like Figure A.

Figure A

Output assembled from three HTML templates and one logic template

The cool part? You can use the same header and footer template across your entire Web site just by importing it as needed. Heck, you can even customize the header and footer on a per-page basis by using template variables for the volatile data and replacing them with different values in each script (see the $TITLE$ variable in Listing C as an illustration).

The best part? Whenever you want to change the page header or footer for your entire site, your designer only needs to edit a single HTML file!

That's it for now. Look for future articles coming soon, where I'll show you how to use a single template for repeated elements such as table rows or lists, use the result of a function in a template variable, and hook dTemplate up to MySQL for truly dynamic page generation. Make sure you come back for that!

Editor's Picks