diff options
| author | Andreas Brachold <vdr07@deltab.de> | 2007-08-13 18:41:27 +0000 |
|---|---|---|
| committer | Andreas Brachold <vdr07@deltab.de> | 2007-08-13 18:41:27 +0000 |
| commit | bcbf441e09fb502cf64924ff2530fa144bdf52c5 (patch) | |
| tree | f377707a2dac078db8cd0c7d7abfe69ac1006d71 /lib/Template/Tutorial/Web.pod | |
| download | xxv-bcbf441e09fb502cf64924ff2530fa144bdf52c5.tar.gz xxv-bcbf441e09fb502cf64924ff2530fa144bdf52c5.tar.bz2 | |
* Move files to trunk
Diffstat (limited to 'lib/Template/Tutorial/Web.pod')
| -rw-r--r-- | lib/Template/Tutorial/Web.pod | 801 |
1 files changed, 801 insertions, 0 deletions
diff --git a/lib/Template/Tutorial/Web.pod b/lib/Template/Tutorial/Web.pod new file mode 100644 index 0000000..a5ed9bb --- /dev/null +++ b/lib/Template/Tutorial/Web.pod @@ -0,0 +1,801 @@ +#============================================================= -*-perl-*- +# +# Template::Tutorial::Web +# +# DESCRIPTION +# This tutorial provides an introduction to the Template Toolkit and +# a "quick start" guide to getting up to speed. Its primarily focus +# is on using the Template Toolkit to build web content and it covers +# 4 basic areas: using tpage and ttree; using the Template.pm module +# in CGI scripts; writing Apache/mod_perl handlers; and extending the +# toolkit by writing plugins. +# +# AUTHOR +# Andy Wardley <abw@andywardley.com> +# +# COPYRIGHT +# Copyright (C) 1996-2001 Andy Wardley. All Rights Reserved. +# Copyright (C) 1998-2001 Canon Research Centre Europe Ltd. +# +# This module is free software; you can redistribute it and/or +# modify it under the same terms as Perl itself. +# +# REVISION +# +# +#======================================================================== + + +#------------------------------------------------------------------------ +# IMPORTANT NOTE +# This documentation is generated automatically from source +# templates. Any changes you make here may be lost. +# +# The 'docsrc' documentation source bundle is available for download +# from http://www.template-toolkit.org/docs.html and contains all +# the source templates, XML files, scripts, etc., from which the +# documentation for the Template Toolkit is built. +#------------------------------------------------------------------------ + +=head1 NAME + +Template::Tutorial::Web - Generating Web Content Using the Template Toolkit + +=head1 DESCRIPTION + +This tutorial document provides a introduction to the Template Toolkit +and demonstrates some of the typical ways it may be used for +generating web content. It covers the generation of static pages from +templates using the L<tpage|Template::Tools::tpage> and +L<ttree|Template::Tools::ttree> scripts and then goes on to +show dynamic content generation using CGI scripts and Apache/mod_perl +handlers. + +Various features of the Template Toolkit are introduced and described +briefly and explained by use of example. For further information, +see L<Template>, L<Template::Manual> and the various sections within +it. e.g. + + perldoc Template # Template.pm module usage + perldoc Template::Manual # index to manual + perldoc Template::Manual::Config # e.g. configuration options + +The documentation is now also distributed in HTML format (or rather, +in the form of HTML templates). See the 'docs' sub-directory of the +distribution for further information on building the HTML documentation. + +If you're already reading this as part of the HTML documentation, then +you don't need to worry about all that. You can have a seat, sit back. + back and enjoy the rest of the tutorial... + +=head1 INTRODUCTION + +The Template Toolkit is a set of Perl modules which collectively +implement a template processing system. In this context, a template +is a text document containing special markup tags called 'directives'. +A directive is an instruction for the template processor to perform +some action and substitute the result into the document in place of +the original directive. Directives include those to define or insert +a variable value, iterate through a list of values (FOREACH), declare +a conditional block (IF/UNLESS/ELSE), include and process another template +file (INCLUDE) and so on. + +In all other respects, the document is a plain text file and may +contain any other content (e.g. HTML, XML, RTF, LaTeX, etc). Directives +are inserted in the document within the special markup tags which are +'[%' and '%]' by default, but can be changed via the module +configuration options. Here's an example of an HTML document with +additional Template Toolkit directives. + + [% INCLUDE header + title = 'This is an HTML example' + %] + + <h1>Some Interesting Links</h1> + + [% webpages = [ + { url => 'http://foo.org', title => 'The Foo Organisation' } + { url => 'http://bar.org', title => 'The Bar Organisation' } + ] + %] + + Links: + <ul> + [% FOREACH link = webpages %] + <li><a href="[% link.url %]">[% link.title %]</a> + [% END %] + </ul> + + [% INCLUDE footer %] + +This example shows how the INCLUDE directive is used to load and process +separate 'header' and 'footer' template files, including the output in +the current document. These files might look like this: + +header: + + <html> + <head> + <title>[% title %]</title> + </head> + + <body bgcolor="#ffffff"> + +footer: + + <hr> + + <center> + © Copyright 2000 Me, Myself, I + </center> + + </body> + </html> + +The example also uses the FOREACH directive to iterate through the +'webpages' list to build a table of links. In this example, we have +defined this list within the template to contain a number of hash references, +each containing a 'url' and 'title' member. The FOREACH directive +iterates through the list, aliasing 'link' to each item (hash ref). +The B<[% link.url %]> and B<[% link.title %]> directives then access +the individual values in the hash and insert them into the document. + +The following sections show other ways in which data can be defined for +use in a template. + +=head1 GENERATING STATIC PAGES + +Having created a template file we can now process it to generate some +real output. The quickest and easiest way to do this is to use the +F<tpage> script. This is provided as part of the Template Toolkit and +should be installed in your usual Perl bin directory. + +Assuming you saved your template file as 'mypage.html', you would run +the command: + + tpage mypage.html + +This will process the template file, sending the output to STDOUT +(i.e. whizzing past you on the screen). You may want to redirect the +output to a file but be careful not to specify the same name as the +template file, or you'll overwrite it. You may want to use one prefix +for your templates such as '.atml' (for 'Another Template Markup +Language', perhaps?) and the regular '.html' for the output files +(assuming you're creating HTML, that is). Alternatively, you might +redirect the output to another directory. e.g. + + tpage mypage.atml > mypage.html + tpage templates/mypage.html > html/mypage.html + +The B<tpage> script is very basic and only really intended to give you +an easy way to process a template without having to write any Perl code. +A much more flexible tool is B<ttree>, described below, but for now let's +look at the output generated by processing the above example (some +whitespace removed for brevity): + + <html> + <head> + <title>This is an HTML example</title> + </head> + + <body bgcolor="#ffffff"> + + <h1>Some Interesting Links</h1> + + Links: + <ul> + <li><a href="http://foo.org">The Foo Organsiation</a> + <li><a href="http://bar.org">The Bar Organsiation</a> + </ul> + + <hr> + + <center> + © Copyright 2000 Me, Myself, I + </center> + + </body> + </html> + +The F<header> and F<footer> template files have been included (assuming +you created them and they're in the current directory) and the link data +has been built into an HTML list. + +The F<ttree> script, also distributed as part of the Template Toolkit, +provides a more flexible way to process template documents. The first +time you run the script, it will ask you if it should create a +configuration file, usually called '.ttreerc' in your home directory. +Answer 'y' to have it create the file. + +The F<ttree> documentation describes how you can change the location +of this file and also explains the syntax and meaning of the various +options in the file. Comments are written to the sample configuration +file which should also help. + + perldoc ttree + ttree -h + +In brief, the configuration file describes the directories in which +template files are to be found (src), where the corresponding output +should be written to (dest), and any other directories (lib) that may +contain template files that you plan to INCLUDE into your source +documents. You can also specify processing options (such as 'verbose' +and 'recurse') and provide regular expression to match files that you +don't want to process (ignore, accept) or should be copied instead of +processed (copy). + +An example F<.ttreerc> file is shown here: + +$HOME/.ttreerc: + verbose + recurse + + # this is where I keep other ttree config files + cfg = ~/.ttree + + src = ~/websrc/src + lib = ~/websrc/lib + dest = ~/public_html/test + + ignore = \b(CVS|RCS)\b + ignore = ^# + +You can create many different configuration files and store them +in the directory specified in the 'cfg' option, shown above. You then +add the C<-f filename> option to F<ttree> to have it read that file. + +When you run the script, it compares all the files in the 'src' directory +(including those in sub-directories if the 'recurse' option is set), with +those in the 'dest' directory. If the destination file doesn't exist or +has an earlier modification time than the corresponding source file, then +the source will be processed with the output written to the destination +file. The C<-a> option forces all files to be processed, regardless of +modification times. + +The script I<doesn't> process any of the files in the 'lib' directory, +but it does add it to the INCLUDE_PATH for the template processor so +that it can locate these files via an INCLUDE or PROCESS directive. +Thus, the 'lib' directory is an excellent place to keep template elements +such as header, footers, etc., that aren't complete documents in their +own right. + +You can also specify various Template Toolkit options from the configuration +file. Consult the B<ttree> documentation and help summary (C<ttree -h>) +for full details. e.g. + +$HOME/.ttreerc: + pre_process = config + interpolate + post_chomp + +The 'pre_process' option allows you to specify a template file which +should be processed before each file. Unsurprisingly, there's also a +'post_process' option to add a template after each file. In the +fragment above, we have specified that the 'config' template should be +used as a prefix template. We can create this file in the 'lib' +directory and use it to define some common variables, including those +web page links we defined earlier and might want to re-use in other +templates. We could also include an HTML header, title, or menu bar +in this file which would then be prepended to each and every template +file, but for now we'll keep all that in a separate 'header' file. + +$lib/config: + + [% root = '~/abw' + home = "$root/index.html" + images = "$root/images" + email = 'abw@wardley.org' + graphics = 1 + webpages = [ + { url => 'http://foo.org', title => 'The Foo Organsiation' } + { url => 'http://bar.org', title => 'The Bar Organsiation' } + ] + %] + +Assuming you've created or copied the 'header' and 'footer' files from the +earlier example into your 'lib' directory, you can now start to create +web pages like the following in your 'src' directory and process them +with F<ttree>. + +$src/newpage.html: + + [% INCLUDE header + title = 'Another Template Toolkit Test Page' + %] + + <a href="[% home %]">Home</a> + <a href="mailto:[% email %]">Email</a> + + [% IF graphics %] + <img src="[% images %]/logo.gif" align=right width=60 height=40> + [% END %] + + [% INCLUDE footer %] + +Here we've shown how pre-defined variables can be used as flags to +enable certain feature (e.g. 'graphics') and to specify common items +such as an email address and URL's for the home page, images directory +and so on. This approach allows you to define these values once so +that they're consistent across all pages and can easily be changed to +new values. + +When you run B<ttree>, you should see output similar to the following +(assuming you have the verbose flag set). + + ttree 1.14 (Template Toolkit version 1.02a) + + Source: /home/abw/websrc/src + Destination: /home/abw/public_html/test + Include Path: [ /home/abw/websrc/lib ] + Ignore: [ \b(CVS|RCS)\b, ^# ] + Copy: [ ] + Accept: [ * ] + + + newpage.html + +The '+' before 'newpage.html' shows that the file was processed, with +the output being written to the destination directory. If you run the +same command again, you'll see the following line displayed instead +showing a '-' and giving a reason why the file wasn't processed. + + - newpage.html (not modified) + +It has detected a 'newpage.html' in the destination directory which is +more recent than that in the source directory and so hasn't bothered +to waste time re-processing it. To force all files to be processed, +use the C<-a> option. You can also specify one or more filenames as +command line arguments to F<ttree>: + + tpage newpage.html + +This is what the destination page looks like. + +$dest/newpage.html: + + <html> + <head> + <title>Another Template Toolkit Test Page</title> + </head> + + <body bgcolor="#ffffff"> + + <a href="~/abw/index.html">Home</a> + <a href="mailto:abw@wardley.org">Email me</a> + + <img src="~/abw/images/logo.gif" align=right width=60 height=40> + + <hr> + + <center> + © Copyright 2000 Me, Myself, I + </center> + + </body> + </html> + +You can add as many documents as you like to the 'src' directory and +F<ttree> will apply the same process to them all. In this way, it is +possible to build an entire tree of static content for a web site with +a single command. The added benefit is that you can be assured of +consistency in links, header style, or whatever else you choose to +implement in terms of common templates elements or variables. + +=head1 DYNAMIC CONTENT GENERATION VIA CGI SCRIPT + +The L<Template|Template> module provides a simple front-end to the Template +Toolkit for use in CGI scripts and Apache/mod_perl handlers. Simply +'use' the Template module, create an object instance with the new() +method and then call the process() method on the object, passing the +name of the template file as a parameter. The second parameter passed +is a reference to a hash array of variables that we want made available +to the template: + + #!/usr/bin/perl -w + + use strict; + use Template; + + my $file = 'src/greeting.html'; + my $vars = { + message => "Hello World\n" + }; + + my $template = Template->new(); + + $template->process($file, $vars) + || die "Template process failed: ", $template->error(), "\n"; + +So that our scripts will work with the same template files as our earlier +examples, we'll can add some configuration options to the constructor to +tell it about our environment: + + my $template->new({ + # where to find template files + INCLUDE_PATH => '/home/abw/websrc/src:/home/abw/websrc/lib', + # pre-process lib/config to define any extra values + PRE_PROCESS => 'config', + }); + +Note that here we specify the 'config' file as a PRE_PROCESS option. +This means that the templates we process can use the same global +variables defined earlier for our static pages. We don't have to +replicate their definitions in this script. However, we can supply +additional data and functionality specific to this script via the hash +of variables that we pass to the process() method. + +These entries in this hash may contain simple text or other values, +references to lists, others hashes, sub-routines or objects. The Template +Toolkit will automatically apply the correct procedure to access these +different types when you use the variables in a template. + +Here's a more detailed example to look over. Amongst the different +template variables we define in C<$vars>, we create a reference to a +CGI object and a 'get_user_projects' sub-routine. + + #!/usr/bin/perl -w + + use strict; + use Template; + use CGI; + + $| = 1; + print "Content-type: text/html\n\n"; + + my $file = 'userinfo.html'; + my $vars = { + 'version' => 3.14, + 'days' => [ qw( mon tue wed thu fri sat sun ) ], + 'worklist' => \&get_user_projects, + 'cgi' => CGI->new(), + 'me' => { + 'id' => 'abw', + 'name' => 'Andy Wardley', + }, + }; + + sub get_user_projects { + my $user = shift; + my @projects = ... # do something to retrieve data + return \@projects; + } + + my $template = Template->new({ + INCLUDE_PATH => '/home/abw/websrc/src:/home/abw/websrc/lib', + PRE_PROCESS => 'config', + }); + + $template->process($file, $vars) + || die $template->error(); + +Here's a sample template file that we might create to build the output +for this script. + +$src/userinfo.html: + + [% INCLUDE header + title = 'Template Toolkit CGI Test' + %] + + <a href="mailto:[% email %]">Email [% me.name %]</a> + + <p>This is version [% version %]</p> + + <h3>Projects</h3> + <ul> + [% FOREACH project = worklist(me.id) %] + <li> <a href="[% project.url %]">[% project.name %]</a> + [% END %] + </ul> + + [% INCLUDE footer %] + +This example shows how we've separated the Perl implementation (code) from +the presentation (HTML) which not only makes them easier to maintain in +isolation, but also allows the re-use of existing template elements +such as headers and footers, etc. By using template to create the +output of your CGI scripts, you can give them the same consistency +as your static pages built via L<ttree|Template::Tools::ttree> or +other means. + +Furthermore, we can modify our script so that it processes any one of a +number of different templates based on some condition. A CGI script to +maintain a user database, for example, might process one template to +provide an empty form for new users, the same form with some default +values set for updating an existing user record, a third template for +listing all users in the system, and so on. You can use any Perl +functionality you care to write to implement the logic of your +application and then choose one or other template to generate the +desired output for the application state. + +=head1 DYNAMIC CONTENT GENERATION VIA APACHE/MOD_PERL HANDLER + +B<NOTE:> the Apache::Template module is now available from CPAN +and provides a simple and easy to use Apache/mod_perl interface to the +Template Toolkit. It's only in it's first release (0.01) at the time +of writing and it currently only offers a fairly basic facility, but +it implements most, if not all of what is described below, and it +avoids the need to write your own handler. However, in many cases, +you'll want to write your own handler to customise processing for your +own need, and this section will show you how to get started. + +The Template module can be used in a similar way from an Apache/mod_perl +handler. Here's an example of a typical Apache F<httpd.conf> file: + + PerlModule CGI; + PerlModule Template + PerlModule MyOrg::Apache::User + + PerlSetVar websrc_root /home/abw/websrc + + <Location /user/bin> + SetHandler perl-script + PerlHandler MyOrg::Apache::User + </Location> + +This defines a location called '/user/bin' to which all requests will +be forwarded to the handler() method of the MyOrg::Apache::User +module. That module might look something like this: + + package MyOrg::Apache::User; + + use strict; + use vars qw( $VERSION ); + use Apache::Constants qw( :common ); + use Template qw( :template ); + use CGI; + + $VERSION = 1.59; + + sub handler { + my $r = shift; + + my $websrc = $r->dir_config('websrc_root') + or return fail($r, SERVER_ERROR, + "'websrc_root' not specified"); + + my $template = Template->new({ + INCLUDE_PATH => "$websrc/src/user:$websrc/lib", + PRE_PROCESS => 'config', + OUTPUT => $r, # direct output to Apache request + }); + + my $params = { + uri => $r->uri, + cgi => CGI->new, + }; + + # use the path_info to determine which template file to process + my $file = $r->path_info; + $file =~ s[^/][]; + + $r->content_type('text/html'); + $r->send_http_header; + + $template->process($file, $params) + || return fail($r, SERVER_ERROR, $template->error()); + + return OK; + } + + sub fail { + my ($r, $status, $message) = @_; + $r->log_reason($message, $r->filename); + return $status; + } + +The handler accepts the request and uses it to determine the 'websrc_root' +value from the config file. This is then used to define an INCLUDE_PATH +for a new Template object. The URI is extracted from the request and a +CGI object is created. These are both defined as template variables. + +The name of the template file itself is taken from the PATH_INFO element +of the request. In this case, it would comprise the part of the URL +coming after '/user/bin', e.g for '/user/bin/edit', the template file +would be 'edit' located in "$websrc/src/user". The headers are sent +and the template file is processed. All output is sent directly to the +print() method of the Apache request object. + +=head1 USING PLUGINS TO EXTEND FUNCTIONALITY + +As we've already shown, it is possible to bind Perl data and functions +to template variables when creating dynamic content via a CGI script +or Apache/mod_perl process. The Template Toolkit also supports a +plugin interface which allows you define such additional data and/or +functionality in a separate module and then load and use it as +required with the USE directive. + +The main benefit to this approach is that you can load the extension into +any template document, even those that are processed "statically" by +F<tpage> or F<ttree>. You I<don't> need to write a Perl wrapper to +explicitly load the module and make it available via the stash. + +Let's demonstrate this principle using the DBI plugin written by Simon +Matthews E<lt>sam@knowledgepool.comE<gt>. You can create this +template in your 'src' directory and process it using F<ttree> to see +the results. Of course, this example relies on the existence of the +appropriate SQL database but you should be able to adapt it to your +own resources, or at least use it as a demonstrative example of what's +possible. + + [% INCLUDE header + title = 'User Info' + %] + + [% USE DBI('dbi:mSQL:mydbname') %] + + <table border=0 width="100%"> + <tr> + <th>User ID</th> + <th>Name</th> + <th>Email</th> + </tr> + + [% FOREACH user = DBI.query('SELECT * FROM user ORDER BY id') %] + <tr> + <td>[% user.id %]</td> + <td>[% user.name %]</td> + <td>[% user.email %]</td> + </tr> + [% END %] + + </table> + + [% INCLUDE footer %] + +A plugin is simply a Perl module in a known location and conforming to +a known standard such that the Template Toolkit can find and load it +automatically. You can create your own plugin by inheriting from the +F<Template::Plugin> module. + +Here's an example which defines some data items ('foo' and 'people') +and also an object method ('bar'). We'll call the plugin 'FooBar' for +want of a better name and create it in the 'MyOrg::Template::Plugin::FooBar' +package. We've added a 'MyOrg' to the regular 'Template::Plugin::*' package +to avoid any conflict with existing plugins. + +You can create a module stub using the Perl utlity F<h2xs>: + + h2xs -A -X -n MyOrg::Template::Plugin::FooBar + +This will create a directory structure representing the package name +along with a set of files comprising your new module. You can then +edit FooBar.pm to look something like this: + + package MyOrg::Template::Plugin::FooBar; + + use Template::Plugin; + use vars qw( $VERSION ); + use base qw( Template::Plugin ); + + $VERSION = 1.23; + + sub new { + my ($class, $context, @params) = @_; + + bless { + _CONTEXT => $context, + foo => 25, + people => [ 'tom', 'dick', 'harry' ], + }, $class; + } + + sub bar { + my ($self, @params) = @_; + # ...do something... + return $some_value; + } + +The plugin constructor new() receives the class name as the first +parameter, as is usual in Perl, followed by a reference to something +called a Template::Context object. You don't need to worry too much +about this at the moment, other than to know that it's the main +processing object for the Template Toolkit. It provides access to the +functionality of the processor and some plugins may need to +communicate with it. We don't at this stage, but we'll save the +reference anyway in the '_CONTEXT' member. The leading underscore is +a convention which indicates that this item is private and the +Template Toolkit won't attempt to access this member. The other +members defined, 'foo' and 'people' are regular data items which will be +made available to templates using this plugin. Following the context +reference are passed any additional parameters specified with the +USE directive, such as the data source parameter, 'dbi:mSQL:mydbname', +that we used in the earlier DBI example. + +If you used F<h2xs> to create the module stub then you'll already +have a Makefile.PL and you can incite the familiar incantation to +build and install it. Don't forget to add some tests to test.pl! + + perl Makefile.PL + make + make test + make install + +If you don't or can't install it to the regular place for your Perl +modules (perhaps because you don't have the required privileges) then +you can set the PERL5LIB environment variable to specify another location. +If you're using F<ttree> then you can add the following line to your +configuration file instead. This has the effect of add '/path/to/modules' +to the @INC array to a similar end. + +$HOME/.ttreerc: + + perl5lib = /path/to/modules + +One further configuration item must be added to inform the toolkit of +the new package name we have adopted for our plugins: + +$HOME/.ttreerc: + + plugin_base = 'MyOrg::Template::Plugin' + +If you're writing Perl code to control the Template modules directly, +then this value can be passed as a configuration parameter when you +create the module. + + use Template; + + my $template = Template->new({ + PLUGIN_BASE => 'MyOrg::Template::Plugin' + }); + +Now we can create a template which uses this plugin: + + [% INCLUDE header + title = 'FooBar Plugin Test' + %] + + [% USE FooBar %] + + Some values available from this plugin: + [% FooBar.foo %] [% FooBar.bar %] + + The users defined in the 'people' list: + [% FOREACH uid = FooBar.people %] + * [% uid %] + [% END %] + + [% INCLUDE footer %] + +The 'foo', 'bar' and 'people' items of the FooBar plugin are +automatically resolved to the appropriate data items or method calls +on the underlying object. + +Using this approach, it is possible to create application +functionality in a single module which can then be loaded and used on +demand in any template. The simple interface between template +directives and plugin objects allows complex, dynamic content to be +built from a few simple template documents without knowing anything +about the underlying implementation. + +=head1 AUTHOR + +Andy Wardley E<lt>abw@andywardley.comE<gt> + +L<http://www.andywardley.com/|http://www.andywardley.com/> + + + + +=head1 VERSION + +Template Toolkit version 2.13, released on 30 January 2004. + +=head1 COPYRIGHT + + Copyright (C) 1996-2004 Andy Wardley. All Rights Reserved. + Copyright (C) 1998-2002 Canon Research Centre Europe Ltd. + +This module is free software; you can redistribute it and/or +modify it under the same terms as Perl itself. + + + +=cut + +# Local Variables: +# mode: perl +# perl-indent-level: 4 +# indent-tabs-mode: nil +# End: +# +# vim: expandtab shiftwidth=4: |
