Developer

More dynamic Web templates with dTemplate

Here are tips and techniques to get the most out of the dTemplate engine—everything from using a function in place of a variable value to linking the dTemplate engine with a MySQL database for data-driven templating.

In the previous segment of this tutorial, you learned the basics of the dTemplate engine, from how the engine works to how to use multiple templates on a single page. In this second part, I'll show you a few more techniques to get the most out of dTemplate, including repeating elements, using a function in place of a variable value, and linking the dTemplate engine to a MySQL database for data-driven templating.

Using built-in Perl functions in a template

Let's begin with something simple: using the return value of a function in the call to
parse(). The examples in the previous article involved replacing template variables with hard-coded values. However, it's quite likely that you'll sometimes need to replace a template variable with a value generated from a calculation or function. This simple template illustrates one example:

<!— now.tmpl —>
<html><head></head>
<body>

It is now $NOW$

</body></html>

In this template, the variable $NOW$ must store the current date and time, so its value cannot be hard-coded into a script. Therefore, we must assign a value to this variable from a function that dynamically generates the current time, as in Listing A.

The parse() function will replace the variable $NOW$ with the return value of the function. This is an important capability, as you'll see shortly.

Using custom functions in a template

Just as you can use Perl's built-in functions to assign values to template variables, so also can you define your own. In order to illustrate, consider the following template:

<form>Select from the following options:
<select>
$OPTIONS$
</select>
</form>

Now, I need to generate a series of <option> boxes to replace the $OPTIONS$ variable. Assuming I have the option list available in a Perl array, it's possible to write a simple Perl function that generates this option list through a loop and assigns the list to the $OPTIONS$ variable, as in Listing B.

In this case, the value assigned to the $OPTIONS$ variable is actually a user-defined Perl subroutine. This subroutine reads the contents of the @countries array and generates a series of <option> elements, which are then returned to the enclosing code block. The parse() function interpolates this returned value with the $OPTIONS$ placeholder to create the result shown in Listing C.

Repeating elements

Another way to do the same thing is to split the template into two pieces—one for the main form and one for the element that repeats. This is a somewhat more elegant alternative to the example on the previous page. Consider the following two templates, form.tmpl:

<!— form.tmpl —>
<form>
Select from the following options:
<select>$OPTIONS$</select>
</form>

and option.tmpl:

<!— option.tmpl —>
<option>$ITEM$</option>

In this case, I first need to generate the option list from the option.tmpl template by repeatedly calling parse() on it and appending the output from each run to the previous runs. You've already seen this technique in the first part of this article. Once the option list is generated, it's a simple matter to parse the outer template and assign the option list to the $OPTIONS$ variable, as in Listing D.

Example application:
Using dTemplate with MySQL

Now, how about putting everything you've learned into practice. This next example shows you how to hook your dTemplate system up to a MySQL database for dynamic page generation. Here I'll assume the existence of a MySQL table containing user information, as in Listing E.

My script must generate two pages, both driven off this table. The first page is an index of user names generated when the script is called without any arguments. The second is a page containing details on a specific user, and it requires the user name to be provided to the script.

Both pages can be generated from the same script simply by keying on the presence or absence of a user name in the script input. The first step is to generate the templates for the two pages. First, the index page, index.tmpl:

<!— index.tmpl —>
<html><head></head>
<body>

Available users:

<ul>$LIST$</ul>

</body></html>

And for an individual list item, li.tmpl:

<!— li.tmpl —>
<li><a href="/cgi-bin/script.cgi?username=$NAME$">$NAME$</li>

And here's the template for the user details page, detail.tmpl:

<!— detail.tmpl —>
<html><head></head>
<body>

User information for <i>$USER$</i>:
<p>
<table border="1" cellspacing="0" cellpadding="5"> <tr>
<td>First name</td>
<td>Last name</td>
<td>Date of birth</td>
<td>Nationality</td>
<td>Age</td>
</tr>
<tr>
<td>$FNAME$</td>
<td>$LNAME$</td>
<td>$DOB$</td>
<td>$NAT$</td>
<td>$AGE$</td>
</tr>
</table>

</body></html>

The script that does all the work is in Listing F. It combines two of Perl's most powerful modules, CGI.pm and DBI.pm, with the dTemplate module.

First, a set of template objects is created, one for each template, and a connection is opened to MySQL in preparation for subsequent queries. Then, depending on whether the script is sent a user name, a query is generated to either obtain a list of users or the record for a specific user. The values returned by the query are then inserted into the template.

Figure A is a screenshot of what the final index page should look like, and Figure B is the detail page:

Figure A

Index page generated by Listing F

Figure B

Detail page generated by Listing F

Notice that the user list in the index page is generated incrementally using the technique demonstrated previously, while each user's age is calculated from the date of birth within the query itself using MySQL's YEAR() function.

I hope the numerous examples and techniques presented in this article give you some insight into how a template system works and encourage you to try it for yourself. As you uncover interesting tips or tricks of your own, come back here and share them on the discussion page for this article.

Editor's Picks

Free Newsletters, In your Inbox