|
|
Flexible CGI output with HTML templates
The problem
Consider our free search engine script. It
is an excellent application, but it wouldn't be very helpful for others if it could display its results
only in the output page format that we use for our site. Somebody else's site will probably need the output
page to contain site-specific navigation links, different colors, or even a completely different layout
concept.
It is not uncommon to see CGI programs that contain the HTML code that is returned to the browser, inside
one or more print statements in the code of the script. Clearly this is not a good idea, since it makes it
at least difficult, if not nearly impossible, for a non-programmer to alter the output format. At best,
a webmaster with little understanding of perl could identify the HTML code inside the program and alter
some obvious items, like colours. Still, as applications grow more complex, this approach becomes even
more difficult to manage. If control structures (if, while etc) are being used
to generate the output, or if there are multiple pages of output composed by chunks of html that
are being generated in different places in the code, even someone who is comfortable with perl could find it
hard to figure out how to alter the look of the output. And this is not the only problem. The code itself
becomes difficult to manage and maintain. Program code is difficult to read an maintain on its
own right. Cluttering it with HTML here and there does not help the situation at all.
I will describe a different approach to the problem here, the one that we use for our programs and which proves to
be a very good solution for almost any type of application. The idea in this approach is to isolate the HTML
code in a separate file, which we call a template. A template is just like any regular HTML file,
but it contains some special markup dictating where to insert the various dynamic data that will be produced
by the CGI program. The program need only be concerned with generating the actual dynamic content, then it
can simply insert it in appropriate place in the template and thus come up with the final output.
What a template looks like
The only thing that sets a template apart from a regular HTML file is that it contains comments of the form
<!--cgi:variable-->. Such comments will be identified by the CGI program and replaced with the
appropriate value for variable. The template may contain references to as many such variables as the
CGI program is made to define. For example, take our search engine program. On the top of the search results page
there appears some text saying what search was made and how many results it came up with. Assuming the program
defines variables search_string and total_results, our template could look like:
<HTML>
...
Your search for <b><!--cgi:search_string--></b>
resulted in <b><!--cgi:total_results--></b> matching pages.
...
</HTML>
Filling in the template
A simple way of doing this is the following:
open(TEMPLATE, $template_file);
while(<TEMPLATE>) {
$buffer .= $_;
}
$buffer =~ s/<!--cgi:search_string-->/$search_string/g;
$buffer =~ s/<!--cgi:total_results-->/$total_results/g;
print $buffer;
This will do the job, but we can certainly do much better than that. A realistic CGI-based application might contain
many scripts generating many pages each, and each of those pages might contain much more than just a handful of
variable data. Clearly we could write something much more general, a little module, that can handle output generation
in the same way, but without requiring the programmer to explicitly perform substitutions of the template directives
in the CGI program.
As I already mentioned, we use that technique in all our programs here at Perlfect, and to make our life easier
we have made a simple module that encapsulates all the functionality relating to templates that could be of use
for CGI programming. The module is freely available
for anyone to download and use for their own programs.
To introduce you to the use of Perlfect::Template I will show a simple example:
my $template = new Perlfect::Template("template.html");
my %data = (
name => 'Nick',
email => 'nick@perlfect.com',
homepage => 'http://www.perlfect.com',
);
my $html = $template->cast(\%data);
First of all we create a Perlfect::Template object corresponding to the template file
we want to use. The filename (or fully qualified path to it) is passed as an argument to the object constructor
that returns a reference to the newly created object.
Then we prepare the data that we are going to cast to the template. Perlfect::Template expects us to
supply it with a reference to a hash table (associative array) mapping data keys (template variables) to the values
that should be inserted for them in the template. Thus all the processing done by the CGI program should end up
defining a set of such key-value pairs in a hash reflecting the dynamic content of the output.
Finally, we call the cast method of the template object passing a reference to our data hash.
The cast method does not alter the template, but simply uses it to produce a filled-in copy of it that is
returned by the call. That means, that you can reuse a template as much as you like in a program. This allows you
to construct your output from 'sub-templates'. For example, in our search engine script, there is one template that
defines the general layout of the results page, but there is also a template that defines the format of a single
result listing. The program uses the latter to generate result listings by substituting, title, description, url,
score, etc and thenputs them all together and inserts them in the general layout template. To create the result
listings we only create one template object and use it for all results, each time passing a different hash reference
to it. This has the advantage that the template file is read only once and that the processing needed to generate an
other instance of the html output is minimal.
Passing substitution handlers..
In most cases the functionality we discussed so far is more than enough to do the job. There are cases though where
passing static values for substitution in a template is a too restrictive mechanism. Sometimes you want the template
to be able to describe not only the location of the substitutions but also some dynamic behaviour. In the example above
I might want to let the template author choose whether the homepage url should appear in linked or plain text form.
Of course, the template variable could just store the url and the template could contain a directive:
<a href="<!--cgi:homepage-->"><!--cgi:homepage--></a> to construct the linked
form, but in other situations ther might not be such workarounds. I would like to let the user pass parameters
in a template directive, and instead of substituting a static string for the directive, I would like the substitution
string to be generated by a function that will be called with the parameters in the directive.
Perlfect::Template allows you to use references to subroutines instead of scalars as values of the substitution hash.
When a directive for suvh a template variable (that really is a subroutine) is met, Perlfect::Template will arrange
for the subroutine to be called and will use ts return value as a substitution string. Further if the template directive
includes arguments in parentheses as in <!--cgi:homepage('linked')--> the subroutine will be passed
those aruments using perl's standard argument passing mechanism. Arguments in the parentheses follow standard perl
syntax for subroutine calls.
So let's review our example above, now using the subroutine calling mechanism...
my $template = new Perlfect::Template("template.html");
my %data = (
name => 'Nick',
email => 'nick@perlfect.com',
homepage => sub {
if($_[0] eq 'linked') { return ... }
else { return ... }
}
);
my $html = $template->cast(\%data);
And who said it's only for HTML?
A final note to be made is that, while this tool was initially developed to aid the writing of CGI scripts that
produce HTML output, it is absolutely fine to use for any kind of program that needs to format text files into
a configurable layout. For example, one great use we've found is to create personalized email from a standard
text template of the message and a database of names and email addresses of the recipients. In general any text
file who is not likely to clash syntactically with the directive format of Perlfect::Template is perfectly
suitable for processing with it.
Have fun programming with Perlfect::Template, and don't hesitate to
contact us and tell us what you think about it, or if you would
suggest any extensions/modifications to it.
Comments
|
Mike | Posted at 3:03pm on Thursday, March 8th, 2007 | Cool |
kris | Posted at 10:15am on Wednesday, April 18th, 2007 | Hi,
I am not able to download the perlfect template. Could you please check the link? |
gamal | Posted at 12:57pm on Tuesday, April 1st, 2008 | this is good |
mahtab | Posted at 7:27am on Monday, May 12th, 2008 | the templates are free? |
333 | Posted at 9:13am on Monday, June 16th, 2008 | intriguing |
Will | Posted at 6:40am on Friday, September 5th, 2008 | Your template link doesnt work .. i guess ill keep googling |
avnpratheep.m | Posted at 12:05am on Friday, October 10th, 2008 | It's very helpful to me...
I need some templates, send to me on aruliba@gmail.com |
Anonymous | Posted at 9:46am on Thursday, November 13th, 2008 | from mohit raj yamuna nagar ....it is good |
mohit raj yamuna nagar | Posted at 10:04am on Thursday, November 13th, 2008 | this is good |
Vinay | Posted at 10:25am on Tuesday, September 29th, 2009 | This is good |
Shelley Midkiff | Posted at 3:24pm on Wednesday, April 7th, 2010 | Is the template still available? Or can you perhaps point me to some other site?
Thanks
Shelley Golard Midkiff
sgolard@uw.edu |
amy | Posted at 2:15pm on Tuesday, July 20th, 2010 | thanks for posting this! |
somasdo | Posted at 2:37am on Monday, October 11th, 2010 | i think kosofy is better than facebook |
Anonymous | Posted at 2:37am on Monday, October 11th, 2010 | i think kosofy is better than facebook |
Anonymous | Posted at 2:38am on Monday, October 11th, 2010 | i think kosofy is better than facebook |
Anonymous | Posted at 2:38am on Monday, October 11th, 2010 | www.kosofy.co.cc |
Joe | Posted at 9:43am on Saturday, April 2nd, 2011 | Just checking it works! |
rony | Posted at 5:27am on Tuesday, September 20th, 2011 | i do,nt like |
home loans | Posted at 8:27am on Tuesday, October 11th, 2011 | If you want to buy a house, you will have to receive the personal loans. Furthermore, my mother always takes a bank loan, which occurs to be really firm. |
THEJASWINI | Posted at 2:52am on Tuesday, November 8th, 2011 | Hi,
I hav created html file to get output which i will be getting by perl script.. But when i run html file i m not able to get perl script output(which has 4 output files). I even tried by creating templates but not working. Plz tel me how to get perlscript outputs with by using html UI? |
adfas | Posted at 10:54am on Wednesday, November 23rd, 2011 | afsdfad |
3hacksTeam | Posted at 4:40pm on Sunday, June 10th, 2012 | fdffgfg |
Sayux | Posted at 9:49am on Monday, August 20th, 2012 | The "something" can be accessed very elsiay with PHP. If you have a web page address that looks like this:index.php? month=september&name=smith&age=24Then you can access those values in PHP like this:This will print septembersmith24.As for accessing a text file, that's easy too:This will read the entire contents of the file textfile.txt into the variable $text, and then print it out for you.You can also access many databases with PHP, I highly recommend you use MySQL. It's a bit too complicated to describe here, though. There are some good references made to good books by folks above. The "Teach Yourself" series is great. |
onjlsdyi | Posted at 1:49am on Tuesday, August 21st, 2012 | RSeml4 dijtlygbgocf |
jfovilq | Posted at 2:09pm on Thursday, August 23rd, 2012 | DEUGK8 ycrkxgrqyuxz |
Comments to date: 25.
|
Suggested Reading
The Official CGI.pm Programming Guide is the definitive manual and guidebook for writing CGI programs
with perl and the CGI library. While the manual distributed with the library as part of perl's documentation is well
written and covers almost anything you'd need to know about using CGI.pm, this book is a useful companion for anyone
making CGI scripts with perl.
CGI Programming is an introductry book for CGI programming, perhaps not the best book I've read.
It covers most topics about the CGI protocol and how to write server side programs to work with it.
Nevertheless, most if not all of the information in this book (as with most books that discuss CGI programming)
can be found in tutorials and references on the web, but if you feel like buying a book anyway, you may want to
consider this one.
Webmaster in a nutshell is a catch-all reference book for webmaster and programmers. It does
not have anuything that you can't find online, but if you're liek me you might want to have all the
stuff you refer to frequently nicely laid out in a well-organized book lying on your desk. If you're looking
for something like that then you'll be happy with this book.
The Perl Cookbook is full of quick solutions to everyday programming problems in perl with explanations
and tips easy to understand even for beginners, but also frequently useful even to more experienced programmers.
The code is clear and straightforward and the topics covered as well-thought and correspond to real world examples,
so frequently you can literally copy code snippets from the book and fit them in your program. It is a nice complement
for the Camel Book on your bookshelf.
|