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