Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

HTML::Template vs. CGI.pm

by hacker (Priest)
on Nov 10, 2003 at 20:08 UTC ( [id://305949]=perlquestion: print w/replies, xml ) Need Help??

hacker has asked for the wisdom of the Perl Monks concerning the following question:

I've been trying to find some real-world examples of how HTML::Template excels over CGI in terms of outputting lots of repetitive HTML constructs. There are those who claim HTML::Template is better, but I can't find any actual reasons or explanations to back that up. It seems to be based more on personal opinion, than anything else. In my case, I have a portal site I've written, which has LOTS of HTML driving it, and I want to make sure I can easily maintain it, as I continue to add functionality and features.

Here's one example:

Using CGI.pm, I have the following construct:

my @menubar = ( {title =>'home', width =>'10', height =>'9', param =>'home', alt =>'Return to the front page'}, {title =>'donate', width =>'15', height =>'9', param =>'donate', alt =>'Send a donation to help'}, # {...} and so on, 9 menu options ); $cgi->start_div({-id=>'mline'}), $cgi->end_div(), "\n\n", $cgi->start_div({-id=>'tmbox'}); print join " | ", map { $cgi->span({-class => 'mitem'}, $cgi->a({-href => "$script?a=$_->{param}", -title => "$_->{alt}"}, $cgi->img({-src => "i/$_->{param}.png", -border => '0', -width => "$_->{width}", -height => "$_->{height}", -alt => "($_->{alt})"}), " $_->{title} "),),} @menubar; print $cgi->end_div();

Nothing magical, and it prints out those menu options, with the graphic, alt tag, href, and a separator "|" bar between, except after the last one, for visual aquity (thanks bart for the suggestion here).

Now, to do this in HTML::Template, I do the following:

my $template = HTML::Template->new( filename => 'menubar.tmpl'); $template->param(MENUBAR => [ {title =>'home', width =>'10', height =>'9', param =>'home', alt =>'Return to the front page'}, {title =>'donate', width =>'15', height =>'9', param =>'donate', alt =>'Send a donation to help'}, # {...} and so on, 9 menu options ] ); print $template->output(); # Yes, still using CGI.pm here for right now $cgi->start_div({-id=>'mline'}), $cgi->end_div(), "\n\n", $cgi->start_div({-id=>'tmbox'});

And the template for this looks like:

<TMPL_LOOP NAME=BOTTOM_LIST> <span class="mitem"> <a title="<TMPL_VAR NAME=TITLE>" href="?a=<TMPL_VAR NAME=PARAM>"> <img height="<TMPL_VAR NAME=HEIGHT>" border="0" src="i/<TMPL_VAR NAME=PARAM>.png" alt="<TMPL_VAR NAME=ALT>" width="<TMPL_VAR NAME=WIDTH>" /> &nbsp;<TMPL_VAR NAME=PARAM>&nbsp; </a> </span> </TMPL_LOOP>

It basically outputs the same thing, but what I don't understand is... why add the complexity of a separate HTML template (which is much more complicated to maintain and update, and substantially larger in terms of lines-of-code) versus just doing it all in CGI.pm?

What's the draw? What is the benefit of switching over? Is there really any benefit? I can see delegating the HTML portion of template development to web-monkeys, and the code to the developers themselves, but in this case, I am cook, bottle-washer, and captain of this ship, so it exponentially complicates my maintenance with more files to update, more lines of code to manage, and in general, complexity with no perceived added-benefit of using it.

Lastly, are there any other modules that can handle the same/similar sort of construct (dynamic generation of options from array refs, etc.). I've looked briefly into CGI::Application, Text::Template, the horror that is Embperl, and Template Toolkit, and wonder if learning the additional metal-languages and other constructs is really worth the pain. My goal is to refactor the number of static subs of HTML I have into something more modular, manageable, and bite-sized.

Replies are listed 'Best First'.
Re: HTML::Template vs. CGI.pm
by dragonchild (Archbishop) on Nov 10, 2003 at 20:14 UTC
    There are hundreds of good reasons. Here are my personal favorites:
    1. You can output different stuff, depending on user choices. For example, PDF::Template takes the exact same data structure as HTML::Template, but makes a PDF.
    2. You can use different languages, or even co-brand your site.
    3. You can have one person maintain your HTML and one person maintain your code. HTML::Template templates are even maintainable using Dreamweaver, Frontpage, and the like.
    4. Because your code is focusing solely on code and your display stuff is focusing solely on your display stuff.
    5. Because all the monks who have more experience than you are telling you to.

    ------
    We are the carpenters and bricklayers of the Information Age.

    The idea is a little like C++ templates, except not quite so brain-meltingly complicated. -- TheDamian, Exegesis 6

    ... strings and arrays will suffice. As they are easily available as native data types in any sane language, ... - blokhead, speaking on evolutionary algorithms

    Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.

      In addition to these reasons, I like using templates because I can edit my HTML comfortably in Mozilla Composer or Emacs HTML mode, with syntax highlighting, HTML validation, etc.

      Good points. I'm especially fond of points 3 and 4.

      Also, why not ditch CGI.pm totally and use CGI::Simple to get a little performance boost?

      --
      "To err is human, but to really foul things up you need a computer." --Paul Ehrlich

Re: HTML::Template vs. CGI.pm
by jeffa (Bishop) on Nov 10, 2003 at 20:43 UTC

    "... why add the complexity of a separate HTML template ..."

    Because someone added the complexity of an HTML coder to your project. Whenever i write a small app for myself, i usually just pick CGI.pm and be done with it, but anything that involves a team, i use a templating system. I started out with HTML::Template and we use HTML::Template were i work, but must confess that Template Toolkit is very fun stuff.

    However, another issue arrises when you decide to store your menu in a database. Let's see CGI.pm do this easier! ;) (warning: untested)
    $sth = $dbh->prepare("select title,width,height,param,alt from menu"); $sth->execute; $tmpl->param(menu => $sth->fetchall_arrayref({})); print header, $tmpl->output; __DATA__ <tmpl_loop menu> <span class="mitem"> <a title="<tmpl_var title>" href="?a=<tmpl_var param>"> <img height="<tmpl_var height>" border="0" src="i/<tmpl_var param>.png" alt="<tmpl_var alt>" width="<tmpl_var width>" /> &nbsp;<tmpl_var param>&nbsp; </a> </span> </tmpl_loop>
    Also, if you use HTML::Template, you should only be using CGI.pm for three things (excluding uploads):
    1. to print the header
    2. to fetch the params
    3. to create form elements
    You should not be mixing anything else. See Colorized HTML stack trace and my reply for what i think is a good CGI.pm to H::T conversion.

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    
Re: HTML::Template vs. CGI.pm
by samtregar (Abbot) on Nov 10, 2003 at 20:16 UTC
    It's pretty simple: HTML designers can edit HTML::Template templates without knowing any Perl. All they need to learn is a few <tmpl_*> tags. So you can write your app in Perl and every time management decides to change colors you can relax and pass the buck.

    That's why I created HTML::Template, and that's why I still use it today.

    -sam

Re: HTML::Template vs. CGI.pm
by jdtoronto (Prior) on Nov 10, 2003 at 20:18 UTC
    Yes, BUT!

    I think you are using HTML::Template in the same way you would CGI.pm, ask yourself why?

    If you want to write the HTML in terms of programatically generating HTML, then use CGI.pm. But if you want to separate the logic from the presentation, then use HTML::TEmplate as a templating system, not as a poor substitute for CGI.pm!

    I build menues on my sites too. But I actually write them in different ways. So I can maintaint hem OUTSIDE the Perl files.

    jdtoronto

Re: HTML::Template vs. CGI.pm
by hardburn (Abbot) on Nov 10, 2003 at 21:28 UTC

    Your CGI example uses a loop to output the data from a @menubar array, but the same data is hard-coded in your HTML::Template example. You could have kept the array there and modified a lot less code:

    my @menubar = ( . . . ); my $template = HTML::Template->new( filename => 'menubar.tmpl'); $template->param(MENUBAR => [ map {{ title => $_->{title}, width => $_->{width}, height => $_->{height}, param => $_->{param}, alt => $_->{alt}, }} @menubar ]); # Or maybe just: #$template->param(MENUBAR => \@menubar); print $template->output();

    Notice that with CGI.pm, you're doing two things: specifiying what tag to use, and the data to place with that tag. That's one thing too many. In HTML::Template, you're only specifying what the data is, and you let the local HTML monkey worry about what the actual tags are.

    As it happens, since I work at a company with a rather small IT staff, the HTML monkey for my projects is usually me. I still use HTML::Template because it is quite likely that the UI for my projects will change. We have people here who are much better at design then I am, but who don't know much programming. So I stick with the template so that they don't bug me just because the UI needs to change :)

    ----
    I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
    -- Schemer

    : () { :|:& };:

    Note: All code is untested, unless otherwise stated

Re: HTML::Template vs. CGI.pm
by Zed_Lopez (Chaplain) on Nov 10, 2003 at 22:43 UTC

    I'm working on a big complicated system in which I've outputted lots of HTML with CGI.pm (writing tables is still almost irresistibly compact with CGI.pm).

    But despite that we've never had a dedicated HTML person -- it's still engineers writing both HTML and doing the programming -- I've regretted it, and have been very happy we're almost through migrating to a template solution.

    Outputting the HTML programatically makes it too damn easy to do things that'll bite you in the butt... like having a given page ultimately made from bits of codes scattered across your script and multiple modules, such that wanting to change a given something about the page can create a headache first in just finding where to make the change.

    If you want to make comprehensive changes to your pages' appearance, where you have to look is isolated in advance with a templating system.

    Having them intermingled makes it easy to break program logic when you just wanted to make a change to the display elements. You'll probably find and fix the problem readily enough, but probably could have avoided it all along with a templating system in which, when you're modifying, testing and debugging how something looks, you know that's all you're doing.

    Plus all the good advice you've already heard about what happens when an HTML person is added, the advantages of using an HTML editor, etc., etc.

    Unless you're sure the program's a one-time knock-off for only your own use, writing your HTML with CGI.pm is false laziness.

Re: HTML::Template vs. CGI.pm
by argggh (Monk) on Nov 10, 2003 at 21:13 UTC
    I know this is not comme-il-faut, but I have increasingly come to detest templating toolkits myself. If you can get your HTML-monkeys to maintain your templates for you, they're probably great. However, I suspect this is quite often a red herring. At least of I the projects I do involving web stuff only a very few come with ready-to-use HTML-monkeys at my beck and call. And if I still have to maintain my templates myself, why, oh why, should I maintain them in the unholy format that is HTML? And passing data to a templating toolkit -- don't get me started. You either adjust your wonderful controller code the the templating toolkits idea of control and data structures with a sledgehammer, or you (shudder) embed Perl code in your HTML templates.

    (I detest CGI.pm, too, it's not just templating toolkits. It's one of the things I'm good at. Detesting.)

    Lately, I've started to tinker with doing HTML in Perl. It's rather fun, actually. I do thinks like:

    body { div { { class => 'content' }, q{Text content}, table { { width => '100%' }, row { cell { ... }, cell { ... } } } } }
    While I can still separate controller and view, now I'm able to code my view in a sensible syntax, and I can pass stuff back and forth without feeling cuffed and gagged. This is still an experiment, so I'm not sure if it's really a good idea, but it's refreshing.

    (Ok, so this doesn't really answer your question at all. Sice the templating guys are bound to do so though, I just thought I'd share. Sorry.)

      It's been many years since I worked on a project where the HTML was done by the programmers, and I would still prefer templates for various reasons. However, if generating HTML programmatically is your bag, you might like higher-level abstractions like what Bivio does.

      I think you're exaggerating the part about needing to change your data format. Template Toolkit can deal with pretty much any data structure you pass in, and doesn't need in-line Perl to do it.

        I think you're exaggerating the part about needing to change your data format. Template Toolkit can deal with pretty much any data structure you pass in, and doesn't need in-line Perl to do it.
        You're right, that was unfair. Still, you end up catering to templating toolkits' notion of control structures no matter what, be they rigidly formatted data structures or a separate specialized in-line language. I'd like to code my control structures in Perl.
Re: HTML::Template vs. CGI.pm
by Purdy (Hermit) on Nov 11, 2003 at 16:20 UTC

    dragonchild made the excellent point (#4), but just to elaborate, separating your design code follows the recognized MVC paradigm (one Google doc that partially explains it), which is an excellent methodology to follow when programming (unless you're doing some simple "Hello World" kinda stuff).

    I'll also make another quick point while I got the podium: be careful when turning over your HTML::Template files to DreamWeaver web-monkeys - in my experience, DreamWeaver has a tendency to muck up your files with its notion of correct HTML ... for example, template tags within a string or other tags:

    <a href="script.cgi?<!-- TMPL_VAR NAME="foo" ESCAPE=URL -->">Link</a> <input type="checkbox" name="option" value="test" <!-- TMPL_IF NAME="s +elected">SELECTED<!-- /TMPL_IF -->>

    I forget (or I'm so scarred that it's been purged from my recall at the moment) what they get turned into ... it ain't pretty, though. I haven't taken the chance to sit down and go through DreamWeaver's preferences - I believe there's something in there to turn off it's "corrective" nature, but I always make a backup and then compare the two files after the web-monkey is done.

    Peace,

    Jason

Re: HTML::Template vs. CGI.pm
by thraxil (Prior) on Nov 11, 2003 at 17:02 UTC

    in addition to what everyone else has pointed out, HTML::Template has the advantage of being relatively language independent. the template syntax isn't tied to perl, and there are implementations written in python, php, java, and probably other languages. so if you ever decide to switch languages for the backend, you don't have to port the templates. i've successfully converted apps from perl to python and vice versa without touching the template files.

    i've also used HTML::Template to make 'skinnable', or highly customizable web apps. you just throw up a quick admin interface that lets users (or admin users at least) edit the template files that generate content directly through the browser. i have, eg, a quiz/survey/poll engine that uses HTML::Template. it's designed to plug into any site or web application that we need to plug it into. using templates lets us easily customize each instance to fit in graphically.

    and HTML::Template's ability to hook into the CGI and DBI modules, when used properly, reduces a lot of the extra overhead.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://305949]
Approved by jdtoronto
Front-paged by broquaint
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others admiring the Monastery: (7)
As of 2024-03-28 09:48 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found