1Template::Tutorial::WebU(s3e)r Contributed Perl DocumentaTteimopnlate::Tutorial::Web(3)
2
3
4
6 Template::Tutorial::Web - Generating Web Content Using the Template
7 Toolkit
8
10 This tutorial document provides a introduction to the Template Toolkit
11 and demonstrates some of the typical ways it may be used for generating
12 web content. It covers the generation of static pages from templates
13 using the tpage and ttree scripts and then goes on to show dynamic
14 content generation using CGI scripts and Apache/mod_perl handlers.
15
16 Various features of the Template Toolkit are introduced and described
17 briefly and explained by use of example. For further information, see
18 Template, Template::Manual and the various sections within it. e.g
19
20 perldoc Template # Template.pm module usage
21 perldoc Template::Manual # index to manual
22 perldoc Template::Manual::Config # e.g. configuration options
23
24 The documentation is also available in HTML format to read online, or
25 download from the Template Toolkit web site:
26
27 http://template-toolkit.org/docs/
28
30 The Template Toolkit is a set of Perl modules which collectively
31 implement a template processing system.
32
33 A template is a text document with special markup tags embedded in it.
34 By default, the Template Toolkit uses '"[%"' and '"%]"' to denote the
35 start and end of a tag. Here's an example:
36
37 [% INCLUDE header %]
38
39 People of [% planet %], your attention please.
40
41 This is [% captain %] of the
42 Galactic Hyperspace Planning Council.
43
44 As you will no doubt be aware, the plans
45 for development of the outlying regions
46 of the Galaxy require the building of a
47 hyperspatial express route through your
48 star system, and regrettably your planet
49 is one of those scheduled for destruction.
50
51 The process will take slightly less than
52 [% time %].
53
54 Thank you.
55
56 [% INCLUDE footer %]
57
58 Tags can contain simple variables (like "planet" and "captain") and
59 more complex directives that start with an upper case keyword (like
60 "INCLUDE"). A directive is an instruction that tells the template
61 processor to perform some action, like processing another template
62 ("header" and "footer" in this example) and inserting the output into
63 the current template. In fact, the simple variables we mentioned are
64 actually "GET" directives, but the "GET" keyword is optional.
65
66 People of [% planet %], your attention please. # short form
67 People of [% GET planet %], your attention please. # long form
68
69 Other directives include "SET" to set a variable value (the "SET"
70 keyword is also optional), "FOREACH" to iterate through a list of
71 values, and "IF", "UNLESS", "ELSIF" and "ELSE" to declare conditional
72 blocks.
73
74 The Template Toolkit processes all text files equally, regardless of
75 what kind of content they contain. So you can use TT to generate HTML,
76 XML, CSS, Javascript, Perl, RTF, LaTeX, or any other text-based format.
77 In this tutorial, however, we'll be concentrating on generating HTML
78 for web pages.
79
81 Here's an example of a template used to generate an HTML document.
82
83 [% INCLUDE header
84 title = 'This is an HTML example';
85
86 pages = [
87 { url = 'http://foo.org'
88 title = 'The Foo Organisation'
89 }
90 { url = 'http://bar.org'
91 title = 'The Bar Organisation'
92 }
93 ]
94 %]
95 <h1>Some Interesting Links</h1>
96 <ul>
97 [% FOREACH page IN pages %]
98 <li><a href="[% page.url %]">[% page.title %]</a>
99 [% END %]
100 </ul>
101
102 [% INCLUDE footer %]
103
104 This example shows how the "INCLUDE" directive is used to load and
105 process separate '"header"' and '"footer"' template files, including
106 the output in the current document. These files might look something
107 like this:
108
109 header:
110
111 <html>
112 <head>
113 <title>[% title %]</title>
114 </head>
115 <body>
116
117 footer:
118
119 <div class="copyright">
120 © Copyright 2007 Arthur Dent
121 </div>
122 </body>
123 </html>
124
125 The example also uses the "FOREACH" directive to iterate through the
126 '"pages"' list to build a table of links. In this example, we have
127 defined this list within the template to contain a number of hash
128 references, each containing a '"url"' and '"title"' member. The
129 "FOREACH" directive iterates through the list, aliasing '"page"' to
130 each item (in this case, hash array references). The "[% page.url %]"
131 and "[% page.title %]" directives then access the individual values in
132 the hash arrays and insert them into the document.
133
134 Using tpage
135 Having created a template file we can now process it to generate some
136 real output. The quickest and easiest way to do this is to use the
137 tpage script. This is provided as part of the Template Toolkit and
138 should be installed in your usual Perl bin directory.
139
140 Assuming you saved your template file as example.html, you would run
141 the command:
142
143 $ tpage example.html
144
145 This will process the template file, sending the output to "STDOUT"
146 (i.e. whizzing past you on the screen). You may want to redirect the
147 output to a file but be careful not to specify the same name as the
148 template file, or you'll overwrite it. You may want to use one prefix
149 for your templates (e.g. '".tt"') and another (e.g. '".html"') for the
150 output files.
151
152 $ tpage example.tt > example.html
153
154 Or you can redirect the output to another directory. e.g.
155
156 $ tpage templates/example.tt > html/example.html
157
158 The output generated would look like this:
159
160 <html>
161 <head>
162 <title>This is an HTML example</title>
163 </head>
164 <body>
165 <h1>Some Interesting Links</h1>
166 <ul>
167 <li><a href="http://foo.org">The Foo Organsiation</a>
168 <li><a href="http://bar.org">The Bar Organsiation</a>
169 </ul>
170 <div class="copyright">
171 © Copyright 2007 Arthur Dent
172 </div>
173 </body>
174 </html>
175
176 The header and footer template files have been included (assuming you
177 created them and they're in the current directory) and the link data
178 has been built into an HTML list.
179
180 Using ttree
181 The tpage script gives you a simple and easy way to process a single
182 template without having to write any Perl code. The
183 <ttree:Template::Tools::ttree> script, also distributed as part of the
184 Template Toolkit, provides a more flexible way to process a number of
185 template documents in one go.
186
187 The first time you run the script, it will ask you if it should create
188 a configuration file (.ttreerc) in your home directory. Answer "y" to
189 have it create the file.
190
191 The <ttree:Template::Tools::ttree> documentation describes how you can
192 change the location of this file and also explains the syntax and
193 meaning of the various options in the file. Comments are written to the
194 sample configuration file which should also help.
195
196 In brief, the configuration file describes the directories in which
197 template files are to be found ("src"), where the corresponding output
198 should be written to ("dest"), and any other directories ("lib") that
199 may contain template files that you plan to "INCLUDE" into your source
200 documents. You can also specify processing options (such as "verbose"
201 and "recurse") and provide regular expression to match files that you
202 don't want to process ("ignore", "accept")> or should be copied instead
203 of being processed as templates ("copy").
204
205 An example .ttreerc file is shown here:
206
207 $HOME/.ttreerc:
208
209 verbose
210 recurse
211
212 # this is where I keep other ttree config files
213 cfg = ~/.ttree
214
215 src = ~/websrc/src
216 lib = ~/websrc/lib
217 dest = ~/public_html/test
218
219 ignore = \b(CVS|RCS)\b
220 ignore = ^#
221
222 You can create many different configuration files and store them in the
223 directory specified in the "cfg" option, shown above. You then add the
224 "-f filename" option to "ttree" to have it read that file.
225
226 When you run the script, it compares all the files in the "src"
227 directory (including those in sub-directories if the "recurse" option
228 is set), with those in the "dest" directory. If the destination file
229 doesn't exist or has an earlier modification time than the
230 corresponding source file, then the source will be processed with the
231 output written to the destination file. The "-a" option forces all
232 files to be processed, regardless of modification times.
233
234 The script doesn't process any of the files in the "lib" directory, but
235 it does add it to the "INCLUDE_PATH" for the template processor so that
236 it can locate these files via an "INCLUDE", "PROCESS" or "WRAPPER"
237 directive. Thus, the "lib" directory is an excellent place to keep
238 template elements such as header, footers, etc., that aren't complete
239 documents in their own right.
240
241 You can also specify various Template Toolkit options from the
242 configuration file. Consult the ttree documentation and help summary
243 ("ttree -h") for full details. e.g.
244
245 $HOME/.ttreerc:
246
247 pre_process = config
248 interpolate
249 post_chomp
250
251 The "pre_process" option allows you to specify a template file which
252 should be processed before each file. Unsurprisingly, there's also a
253 "post_process" option to add a template after each file. In the
254 fragment above, we have specified that the "config" template should be
255 used as a prefix template. We can create this file in the "lib"
256 directory and use it to define some common variables, including those
257 web page links we defined earlier and might want to re-use in other
258 templates. We could also include an HTML header, title, or menu bar in
259 this file which would then be prepended to each and every template
260 file, but for now we'll keep all that in a separate "header" file.
261
262 $lib/config:
263
264 [% root = '~/abw'
265 home = "$root/index.html"
266 images = "$root/images"
267 email = 'abw@wardley.org'
268 graphics = 1
269 webpages = [
270 { url => 'http://foo.org', title => 'The Foo Organsiation' }
271 { url => 'http://bar.org', title => 'The Bar Organsiation' }
272 ]
273 %]
274
275 Assuming you've created or copied the "header" and "footer" files from
276 the earlier example into your "lib" directory, you can now start to
277 create web pages like the following in your "src" directory and process
278 them with "ttree".
279
280 $src/newpage.html:
281
282 [% INCLUDE header
283 title = 'Another Template Toolkit Test Page'
284 %]
285
286 <a href="[% home %]">Home</a>
287 <a href="mailto:[% email %]">Email</a>
288
289 [% IF graphics %]
290 <img src="[% images %]/logo.gif" align=right width=60 height=40>
291 [% END %]
292
293 [% INCLUDE footer %]
294
295 Here we've shown how pre-defined variables can be used as flags to
296 enable certain feature (e.g. "graphics") and to specify common items
297 such as an email address and URL's for the home page, images directory
298 and so on. This approach allows you to define these values once so
299 that they're consistent across all pages and can easily be changed to
300 new values.
301
302 When you run ttree, you should see output similar to the following
303 (assuming you have the verbose flag set).
304
305 ttree 2.9 (Template Toolkit version 2.20)
306
307 Source: /home/abw/websrc/src
308 Destination: /home/abw/public_html/test
309 Include Path: [ /home/abw/websrc/lib ]
310 Ignore: [ \b(CVS|RCS)\b, ^# ]
311 Copy: [ ]
312 Accept: [ * ]
313
314 + newpage.html
315
316 The "+" in front of the "newpage.html" filename shows that the file was
317 processed, with the output being written to the destination directory.
318 If you run the same command again, you'll see the following line
319 displayed instead showing a "-" and giving a reason why the file wasn't
320 processed.
321
322 - newpage.html (not modified)
323
324 It has detected a "newpage.html" in the destination directory which is
325 more recent than that in the source directory and so hasn't bothered to
326 waste time re-processing it. To force all files to be processed, use
327 the "-a" option. You can also specify one or more filenames as command
328 line arguments to "ttree":
329
330 tpage newpage.html
331
332 This is what the destination page looks like.
333
334 $dest/newpage.html:
335
336 <html>
337 <head>
338 <title>Another Template Toolkit Test Page</title>
339 </head>
340 <body>
341
342 <a href="~/abw/index.html">Home</a>
343 <a href="mailto:abw@wardley.org">Email me</a>
344 <img src="~/abw/images/logo.gif" align=right width=60 height=40>
345
346 <div class="copyright">
347 © Copyright 2007 Arthur Dent
348 </div>
349 </body>
350 </html>
351
352 You can add as many documents as you like to the "src" directory and
353 "ttree" will apply the same process to them all. In this way, it is
354 possible to build an entire tree of static content for a web site with
355 a single command. The added benefit is that you can be assured of
356 consistency in links, header style, or whatever else you choose to
357 implement in terms of common templates elements or variables.
358
360 The Template module provides a simple front-end to the Template Toolkit
361 for use in CGI scripts and Apache/mod_perl handlers. Simply "use" the
362 Template module, create an object instance with the new() method and
363 then call the process() method on the object, passing the name of the
364 template file as a parameter. The second parameter passed is a
365 reference to a hash array of variables that we want made available to
366 the template:
367
368 #!/usr/bin/perl
369 use strict;
370 use warnings;
371 use Template;
372
373 my $file = 'src/greeting.html';
374 my $vars = {
375 message => "Hello World\n"
376 };
377
378 my $template = Template->new();
379
380 $template->process($file, $vars)
381 || die "Template process failed: ", $template->error(), "\n";
382
383 So that our scripts will work with the same template files as our
384 earlier examples, we'll can add some configuration options to the
385 constructor to tell it about our environment:
386
387 my $template->new({
388 # where to find template files
389 INCLUDE_PATH => ['/home/abw/websrc/src', '/home/abw/websrc/lib'],
390 # pre-process lib/config to define any extra values
391 PRE_PROCESS => 'config',
392 });
393
394 Note that here we specify the "config" file as a "PRE_PROCESS" option.
395 This means that the templates we process can use the same global
396 variables defined earlier for our static pages. We don't have to
397 replicate their definitions in this script. However, we can supply
398 additional data and functionality specific to this script via the hash
399 of variables that we pass to the "process()" method.
400
401 These entries in this hash may contain simple text or other values,
402 references to lists, others hashes, sub-routines or objects. The
403 Template Toolkit will automatically apply the correct procedure to
404 access these different types when you use the variables in a template.
405
406 Here's a more detailed example to look over. Amongst the different
407 template variables we define in $vars, we create a reference to a CGI
408 object and a "get_user_projects()" sub-routine.
409
410 #!/usr/bin/perl
411 use strict;
412 use warnings;
413 use Template;
414 use CGI;
415
416 $| = 1;
417 print "Content-type: text/html\n\n";
418
419 my $file = 'userinfo.html';
420 my $vars = {
421 'version' => 3.14,
422 'days' => [ qw( mon tue wed thu fri sat sun ) ],
423 'worklist' => \&get_user_projects,
424 'cgi' => CGI->new(),
425 'me' => {
426 'id' => 'abw',
427 'name' => 'Andy Wardley',
428 },
429 };
430
431 sub get_user_projects {
432 my $user = shift;
433 my @projects = ... # do something to retrieve data
434 return \@projects;
435 }
436
437 my $template = Template->new({
438 INCLUDE_PATH => '/home/abw/websrc/src:/home/abw/websrc/lib',
439 PRE_PROCESS => 'config',
440 });
441
442 $template->process($file, $vars)
443 || die $template->error();
444
445 Here's a sample template file that we might create to build the output
446 for this script.
447
448 $src/userinfo.html:
449
450 [% INCLUDE header
451 title = 'Template Toolkit CGI Test'
452 %]
453
454 <a href="mailto:[% email %]">Email [% me.name %]</a>
455
456 <p>This is version [% version %]</p>
457
458 <h3>Projects</h3>
459 <ul>
460 [% FOREACH project IN worklist(me.id) %]
461 <li> <a href="[% project.url %]">[% project.name %]</a>
462 [% END %]
463 </ul>
464
465 [% INCLUDE footer %]
466
467 This example shows how we've separated the Perl implementation (code)
468 from the presentation (HTML). This not only makes them easier to
469 maintain in isolation, but also allows the re-use of existing template
470 elements such as headers and footers, etc. By using template to create
471 the output of your CGI scripts, you can give them the same consistency
472 as your static pages built via ttree or other means.
473
474 Furthermore, we can modify our script so that it processes any one of a
475 number of different templates based on some condition. A CGI script to
476 maintain a user database, for example, might process one template to
477 provide an empty form for new users, the same form with some default
478 values set for updating an existing user record, a third template for
479 listing all users in the system, and so on. You can use any Perl
480 functionality you care to write to implement the logic of your
481 application and then choose one or other template to generate the
482 desired output for the application state.
483
485 NOTE: the Apache::Template module is available from CPAN and provides a
486 simple and easy to use Apache/mod_perl interface to the Template
487 Toolkit. Although basic, it implements most, if not all of what is
488 described below, and it avoids the need to write your own handler.
489 However, in many cases, you'll want to write your own handler to
490 customise processing for your own need, and this section will show you
491 how to get started.
492
493 The Template module can be used from an Apache/mod_perl handler. Here's
494 an example of a typical Apache httpd.conf file:
495
496 PerlModule CGI;
497 PerlModule Template
498 PerlModule MyOrg::Apache::User
499
500 PerlSetVar websrc_root /home/abw/websrc
501
502 <Location /user/bin>
503 SetHandler perl-script
504 PerlHandler MyOrg::Apache::User
505 </Location>
506
507 This defines a location called "/user/bin" to which all requests will
508 be forwarded to the "handler()" method of the "MyOrg::Apache::User"
509 module. That module might look something like this:
510
511 package MyOrg::Apache::User;
512
513 use strict;
514 use Apache::Constants qw( :common );
515 use Template qw( :template );
516 use CGI;
517
518 our $VERSION = 1.59;
519
520 sub handler {
521 my $r = shift;
522
523 my $websrc = $r->dir_config('websrc_root')
524 or return fail($r, SERVER_ERROR,
525 "'websrc_root' not specified");
526
527 my $template = Template->new({
528 INCLUDE_PATH => "$websrc/src/user:$websrc/lib",
529 PRE_PROCESS => 'config',
530 OUTPUT => $r, # direct output to Apache request
531 });
532
533 my $params = {
534 uri => $r->uri,
535 cgi => CGI->new,
536 };
537
538 # use the path_info to determine which template file to process
539 my $file = $r->path_info;
540 $file =~ s[^/][];
541
542 $r->content_type('text/html');
543 $r->send_http_header;
544
545 $template->process($file, $params)
546 || return fail($r, SERVER_ERROR, $template->error());
547
548 return OK;
549 }
550
551 sub fail {
552 my ($r, $status, $message) = @_;
553 $r->log_reason($message, $r->filename);
554 return $status;
555 }
556
557 The handler accepts the request and uses it to determine the
558 "websrc_root" value from the config file. This is then used to define
559 an "INCLUDE_PATH" for a new Template object. The URI is extracted from
560 the request and a CGI object is created. These are both defined as
561 template variables.
562
563 The name of the template file itself is taken from the "PATH_INFO"
564 element of the request. In this case, it would comprise the part of
565 the URL coming after "/user/bin", e.g for "/user/bin/edit", the
566 template file would be "edit" located in "$websrc/src/user". The
567 headers are sent and the template file is processed. All output is
568 sent directly to the "print()" method of the Apache request object.
569
571 As we've already shown, it is possible to bind Perl data and functions
572 to template variables when creating dynamic content via a CGI script or
573 Apache/mod_perl process. The Template Toolkit also supports a plugin
574 interface which allows you define such additional data and/or
575 functionality in a separate module and then load and use it as required
576 with the "USE" directive.
577
578 The main benefit to this approach is that you can load the extension
579 into any template document, even those that are processed "statically"
580 by "tpage" or "ttree". You don't need to write a Perl wrapper to
581 explicitly load the module and make it available via the stash.
582
583 Let's demonstrate this principle using the "DBI" plugin written by
584 Simon Matthews (available from CPAN). You can create this template in
585 your "src" directory and process it using "ttree" to see the results.
586 Of course, this example relies on the existence of the appropriate SQL
587 database but you should be able to adapt it to your own resources, or
588 at least use it as a demonstrative example of what's possible.
589
590 [% INCLUDE header
591 title = 'User Info'
592 %]
593
594 [% USE DBI('dbi:mSQL:mydbname') %]
595
596 <table border=0 width="100%">
597 <tr>
598 <th>User ID</th>
599 <th>Name</th>
600 <th>Email</th>
601 </tr>
602 [% FOREACH user IN DBI.query('SELECT * FROM user ORDER BY id') %]
603 <tr>
604 <td>[% user.id %]</td>
605 <td>[% user.name %]</td>
606 <td>[% user.email %]</td>
607 </tr>
608 [% END %]
609 </table>
610
611 [% INCLUDE footer %]
612
613 A plugin is simply a Perl module in a known location and conforming to
614 a known standard such that the Template Toolkit can find and load it
615 automatically. You can create your own plugin by inheriting from the
616 Template::Plugin module.
617
618 Here's an example which defines some data items ("foo" and "people")
619 and also an object method ("bar"). We'll call the plugin "FooBar" for
620 want of a better name and create it in the
621 "MyOrg::Template::Plugin::FooBar" package. We've added a "MyOrg" to
622 the regular "Template::Plugin::*" package to avoid any conflict with
623 existing plugins.
624
625 package MyOrg::Template::Plugin::FooBar;
626 use base 'Template::Plugin'
627 our $VERSION = 1.23;
628
629 sub new {
630 my ($class, $context, @params) = @_;
631
632 bless {
633 _CONTEXT => $context,
634 foo => 25,
635 people => [ 'tom', 'dick', 'harry' ],
636 }, $class;
637 }
638
639 sub bar {
640 my ($self, @params) = @_;
641 # ...do something...
642 return $some_value;
643 }
644
645 The plugin constructor "new()" receives the class name as the first
646 parameter, as is usual in Perl, followed by a reference to something
647 called a Template::Context object. You don't need to worry too much
648 about this at the moment, other than to know that it's the main
649 processing object for the Template Toolkit. It provides access to the
650 functionality of the processor and some plugins may need to communicate
651 with it. We don't at this stage, but we'll save the reference anyway in
652 the "_CONTEXT" member. The leading underscore is a convention which
653 indicates that this item is private and the Template Toolkit won't
654 attempt to access this member. The other members defined, "foo" and
655 "people" are regular data items which will be made available to
656 templates using this plugin. Following the context reference are passed
657 any additional parameters specified with the USE directive, such as the
658 data source parameter, "dbi:mSQL:mydbname", that we used in the earlier
659 DBI example.
660
661 If you don't or can't install it to the regular place for your Perl
662 modules (perhaps because you don't have the required privileges) then
663 you can set the PERL5LIB environment variable to specify another
664 location. If you're using "ttree" then you can add the following line
665 to your configuration file instead.
666
667 $HOME/.ttreerc:
668
669 perl5lib = /path/to/modules
670
671 One further configuration item must be added to inform the toolkit of
672 the new package name we have adopted for our plugins:
673
674 $HOME/.ttreerc:
675
676 plugin_base = 'MyOrg::Template::Plugin'
677
678 If you're writing Perl code to control the Template modules directly,
679 then this value can be passed as a configuration parameter when you
680 create the module.
681
682 use Template;
683
684 my $template = Template->new({
685 PLUGIN_BASE => 'MyOrg::Template::Plugin'
686 });
687
688 Now we can create a template which uses this plugin:
689
690 [% INCLUDE header
691 title = 'FooBar Plugin Test'
692 %]
693
694 [% USE FooBar %]
695
696 Some values available from this plugin:
697 [% FooBar.foo %] [% FooBar.bar %]
698
699 The users defined in the 'people' list:
700 [% FOREACH uid = FooBar.people %]
701 * [% uid %]
702 [% END %]
703
704 [% INCLUDE footer %]
705
706 The "foo", "bar", and "people" items of the FooBar plugin are
707 automatically resolved to the appropriate data items or method calls on
708 the underlying object.
709
710 Using this approach, it is possible to create application functionality
711 in a single module which can then be loaded and used on demand in any
712 template. The simple interface between template directives and plugin
713 objects allows complex, dynamic content to be built from a few simple
714 template documents without knowing anything about the underlying
715 implementation.
716
718 Andy Wardley <abw@wardley.org> <http://wardley.org/>
719
721 Copyright (C) 1996-2007 Andy Wardley. All Rights Reserved.
722
723 This module is free software; you can redistribute it and/or modify it
724 under the same terms as Perl itself.
725
726
727
728perl v5.34.0 2022-01-21 Template::Tutorial::Web(3)