Skip to Content

Perl Templating Systems Syndicate content

Dave Sherohman's picture

They say that writing your own templating system is one of Perl's standard rites of passage. I wrote mine near the end of 2002, long before I had heard anyone say that. It was also before I became familiar with CPAN, so I didn't know what was already out there.

Oddly enough, I still use it. It works well enough for the needs of the project I wrote it for, so there hasn't been any real reason to rip it out and replace it, but I haven't used it in any other projects either. Instead, I've gone through a couple others and just this week have changed my preferences once again.

The first templating engine I used, aside from the one I wrote, was CGI::FastTemplate. I don't recall how I ran across it, but I suspect it was just a matter of having discovered CPAN, done a search, and decided I liked its promises of high performance. In retrospect, my memories of it are quite painful, as its templates are completely dumb. It doesn't even let you do a simple repeating section within a single template. Instead, you have to use one template for the repeated section, process it repeatedly in your code, and then insert the final results into the containing template. I didn't mind so much at the time, though, because the one I'd written had similar limitations.

As I continued to follow PerlMonks, I saw repeated mentions of HTML::Template, which was a major improvement, adding basic conditional and looping constructs to its language. I stuck by HTML::Template for many years, watching as HTML::Mason and Template::Toolkit gained in popularity.

Although they were widely-used and everyone spoke well of them, I didn't like Mason or TT conceptually. TT advocates often spoke of the ability to put logic into your templates, while Mason seemed to go beyond that to a full-blown PHP-style "code embedded in HTML" design, but, all the way back to 2002, I had recognized templates primarily as a tool for separating logic from presentation. Perl got a bad name from people producing messes of HTML-embedded-in-code and I have a hard time seeing code-embedded-in-HTML as any better. If anything, I tend to consider it even worse.

Still, though, I work as a freelancer and I can't help noticing where the market is. TT is used in at least a large minority of Perl projects I see advertised, quite likely a majority. So, last Tuesday, as I started in on the web interface to my latest project, I finally broke down and decided to give TT a try - although turning off its EVAL_PERL option was the first thing I did.

The first two hours or so were pretty rough, as I figured out how to set everything up and get the pieces talking to each other correctly. By the end of that first day, though, TT had already repaid those hours with interest. HTML::Template practically requires you to copy all of your data from whatever structures it may already occupy into a new structure laid out specifically to support the template(s) that will be used to render it. TT, on the other hand, seems to be pretty good about letting you just pass it an object, or a hash, or an array of arrays of hashes of objects, or whatever and then dig through it as needed from the template. (I did briefly experiment with HTML::Template::Plugin::Dot which brings similar capabilities to HTML::Template, but many of my clients are on shared hosting. Almost all shared hosts have TT available, but I don't think I've seen a single one offering HTML::Template::Plugin::Dot...)

Today, having gotten the hang of basic template usage in TT, I was turning some text into links and had the good sense to look over the TT docs before starting to work up a mess of code and templates to handle it myself. When I did so, I discovered TT's filter functionality, which was just what I needed. It took me a while to dig up information on how to write custom filters and put that into practice1, but I've got two custom filters up and running now and they're both very slick.

Yeah, I think I'm going to be sticking with TT for a while.


1 The docs didn't mention that piggybacking your filter package inside another package's file won't work. Now that I know that, I can see why it doesn't, but it would have saved me some frustration if I hadn't needed to figure it out through trial and error.

Post new comment