Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
Template::Tutorial::WeUser Contributed Perl DocumentTemplate::Tutorial::Web(3)

NAME
       Template::Tutorial::Web - Generating Web	Content	Using the Template
       Toolkit

Overview
       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 tpage and 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
       Template, 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 also available in HTML format to read online, or
       download	from the Template Toolkit web site:

	   http://template-toolkit.org/docs/

Introduction
       The Template Toolkit is a set of	Perl modules which collectively
       implement a template processing system.

       A template is a text document with special markup tags embedded in it.
       By default, the Template	Toolkit	uses '"[%"' and	'"%]"' to denote the
       start and end of	a tag.	Here's an example:

	   [% INCLUDE header %]

	   People of [%	planet %], your	attention please.

	   This	is [% captain %] of the
	   Galactic Hyperspace Planning	Council.

	   As you will no doubt	be aware, the plans
	   for development of the outlying regions
	   of the Galaxy require the building of a
	   hyperspatial	express	route through your
	   star	system,	and regrettably	your planet
	   is one of those scheduled for destruction.

	   The process will take slightly less than
	   [% time %].

	   Thank you.

	   [% INCLUDE footer %]

       Tags can	contain	simple variables (like "planet"	and "captain") and
       more complex directives that start with an upper	case keyword (like
       "INCLUDE").  A directive	is an instruction that tells the template
       processor to perform some action, like processing another template
       ("header" and "footer" in this example) and inserting the output	into
       the current template. In	fact, the simple variables we mentioned	are
       actually	"GET" directives, but the "GET"	keyword	is optional.

	   People of [%	planet %], your	attention please.      # short form
	   People of [%	GET planet %], your attention please.  # long form

       Other directives	include	"SET" to set a variable	value (the "SET"
       keyword is also optional), "FOREACH" to iterate through a list of
       values, and "IF", "UNLESS", "ELSIF" and "ELSE" to declare conditional
       blocks.

       The Template Toolkit processes all text files equally, regardless of
       what kind of content they contain.  So you can use TT to	generate HTML,
       XML, CSS, Javascript, Perl, RTF,	LaTeX, or any other text-based format.
       In this tutorial, however, we'll	be concentrating on generating HTML
       for web pages.

Generating Static Web Content
       Here's an example of a template used to generate	an HTML	document.

	   [%  INCLUDE header
		 title = 'This is an HTML example';

	       pages = [
		 { url	 = 'http://foo.org'
		   title = 'The	Foo Organisation'
		 }
		 { url	 = 'http://bar.org'
		   title = 'The	Bar Organisation'
		 }
	       ]
	   %]
	      <h1>Some Interesting Links</h1>
	      <ul>
	   [%  FOREACH page IN pages %]
		<li><a href="[%	page.url %]">[%	page.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 something
       like this:

       header:

	   <html>
	     <head>
	       <title>[% title %]</title>
	     </head>
	     <body>

       footer:

	       <div class="copyright">
		 &copy;	Copyright 2007 Arthur Dent
	       </div>
	     </body>
	   </html>

       The example also	uses the "FOREACH" directive to	iterate	through	the
       '"pages"' 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 '"page"'	to
       each item (in this case,	hash array references).	The "[%	page.url %]"
       and "[% page.title %]" directives then access the individual values in
       the hash	arrays and insert them into the	document.

   Using tpage
       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
       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	example.html, you would	run
       the command:

	   $ tpage example.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 (e.g.	 '".tt"') and another (e.g. '".html"') for the
       output files.

	   $ tpage example.tt >	example.html

       Or you can redirect the output to another directory. e.g.

	   $ tpage templates/example.tt	> html/example.html

       The output generated would look like this:

	   <html>
	     <head>
	       <title>This is an HTML example</title>
	     </head>
	     <body>
	       <h1>Some	Interesting Links</h1>
	       <ul>
		 <li><a	href="http://foo.org">The Foo Organsiation</a>
		 <li><a	href="http://bar.org">The Bar Organsiation</a>
	       </ul>
	       <div class="copyright">
		 &copy;	Copyright 2007 Arthur Dent
	       </div>
	     </body>
	   </html>

       The header and 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.

   Using ttree
       The tpage script	gives you a simple and easy way	to process a single
       template	without	having to write	any Perl code. The
       <ttree:Template::Tools::ttree> script, also distributed as part of the
       Template	Toolkit, provides a more flexible way to process a number of
       template	documents in one go.

       The first time you run the script, it will ask you if it	should create
       a configuration file (.ttreerc) in your home directory. Answer "y" to
       have it create the file.

       The <ttree:Template::Tools::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.

       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 being	processed as templates ("copy").

       An example .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
       "-f filename" option to "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 "-a" option	forces all
       files to	be processed, regardless of modification times.

       The script 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", "PROCESS" or	"WRAPPER"
       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 ttree documentation and help summary
       ("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 "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 ttree, you should see output similar to the	following
       (assuming you have the verbose flag set).

	   ttree 2.9 (Template Toolkit version 2.20)

		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 "+" in front	of the "newpage.html" filename 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 "-a"	option.	 You can also specify one or more filenames as command
       line arguments to "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>

	       <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>

	       <div class="copyright">
		 &copy;	Copyright 2007 Arthur Dent
	       </div>
	     </body>
	   </html>

       You can add as many documents as	you like to the	"src" directory	and
       "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.

Dynamic	Content	Generation Via CGI Script
       The 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
	   use strict;
	   use warnings;
	   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 $vars, we create	a reference to a CGI
       object and a "get_user_projects()" sub-routine.

	   #!/usr/bin/perl
	   use strict;
	   use warnings;
	   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 IN 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). This 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 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.

Dynamic	Content	Generation Via Apache/Mod_Perl Handler
       NOTE: the Apache::Template module is available from CPAN	and provides a
       simple and easy to use Apache/mod_perl interface	to the Template
       Toolkit.	 Although basic, 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 from an Apache/mod_perl handler.	Here's
       an example of a typical Apache 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 Apache::Constants qw( :common );
	   use Template	qw( :template );
	   use CGI;

	   our $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.

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 "tpage" or "ttree".  You 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 (available from CPAN). You can create this template in
       your "src" directory and	process	it using "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 IN 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
       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.

	   package MyOrg::Template::Plugin::FooBar;
	   use base 'Template::Plugin'
	   our $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 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 "ttree" then you can add the following line
       to your configuration file instead.

       $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.

AUTHOR
       Andy Wardley <abw@wardley.org> <http://wardley.org/>

COPYRIGHT
       Copyright (C) 1996-2007 Andy Wardley.  All Rights Reserved.

       This module is free software; you can redistribute it and/or modify it
       under the same terms as Perl itself.

perl v5.32.1			  2020-03-30	    Template::Tutorial::Web(3)

NAME | Overview | Introduction | Generating Static Web Content | Dynamic Content Generation Via CGI Script | Dynamic Content Generation Via Apache/Mod_Perl Handler | Using Plugins to Extend Functionality | AUTHOR | COPYRIGHT

Want to link to this manual page? Use this URL:
<https://www.freebsd.org/cgi/man.cgi?query=Template::Tutorial::Web&sektion=3&manpath=FreeBSD+13.0-RELEASE+and+Ports>

home | help