Saturday, November 17, 2007

Smarty Template Engine

Instead of reinventing the wheel I decided to check the existing solutions and came across Smarty, a free web template engine written in PHP. It is exactly the framework I had in mind and already started to develop myself so I just switched to it.

Basically web-development can be divided into two parts: actual programming (database access, data processing etc.) and web-design (interface, data presentation, page make up etc.). Program code generates the content and template engine is responsible for its presentation. This way separation of concerns can be easily achieved.

Features available are quite impressive:
  • Caching
  • Compiling
  • Variable modifiers
  • Template functions
  • Control structures
  • Loops
  • Filters
  • Resources
  • Plug-ins
  • Add-ons
  • Debugging
Everything you might need developing templates. This is how it works. This chunk of code I wrote is outputting the parsed feed posts:

{foreach from=$posts key=id item=post}
 <h1>
 {$post.title}<br />
 {if $lang == 'en'}
  {atom_convert_date date=$post.published}
 {else}
  {rss_convert_date date=$post.pubdate}
 {/if}
 </h1>
 <div class="post">
  {if $lang == "en"}
   {$post.atom_content}
  {else}
   {$post.description}
  {/if}
  <div class="comments">
   {if $lang == "en"}
    <a href="{$post.link}" target="_blank">
    {blogger_comments_number comments=$post.replies_title}
    </a>
   {else}
    <a href="{$post.link}" target="_blank">
    Комментарии
    </a>
   {/if}
  </div>
 </div>
{/foreach}


Variable $posts is assigned with parsed feed object which can be either parsed RSS feed of my Russian blog or parsed Atom feed of my English blog. I defined three custom template functions: atom_convert_date, rss_convert_date and blogger_comments_number to parse the dates and number of comments supplied in the feeds. The code is included to the page skeleton using {include file=$include} statement where $include variable indicates whether parsed feed or just text should be included. The whole page is generated the following way:

$template = new DmitryFi();

$template->assign('lang', $lang);
$template->assign('title', $title);
$template->assign('feed', $feed);
$template->assign('balloon', 'Have a job to offer?<br/>Check my <a href="/cv.xhtml">CV</a>!');
$template->assign('label', $label);

if($posts = @fetch_rss($feed['url']))
{
 $template->assign('include', 'feed.tpl');
 $template->assign('posts', $posts->items);
}
else
{
 $template->assign('include', 'text.tpl');
 $template->assign('text', 'Unable to parse the feed. Please try again later.');
}

$template->display(TEMPLATE.'.tpl');


The result is compiled and stored increasing the performance significantly next time the page is requested.

2 comments:

Pavel B. said...

We have used it for a while in our own project.

Results was good, but sometimes Smarty class forgets changes you have made to him (e.g. assign).

This was because of f*cked $this in PHP4, but in PHP5 everything just good.

Since now I'm writing mostly on Perl I using TemplateToolkit2: http://tt2.org/. It's flexible enough even to read Smarty's files.

PS:
What does mean `@' symbol in @fetch_rss call?

I have never seen this syntax before.

Dmitry said...

It does pretty much the same as in makefiles and DOS/Windows batch files, it suppresses the output. It's useful if you want to have own nice error messages like 'Unable to parse the feed. Please try again later'.