Creating PHP Web Sites with Smarty

I recently relaunched SportsFilter using the site's original web design on top of new programming, replacing a ColdFusion site with one written in PHP. The project turned out to be the most difficult web application I've ever worked on. For months, I kept writing PHP code only to throw it all out and start over as it became a ginormous pile of spaghetti.

Back in July, SportsFilter began crashing frequently and neither I nor the hosting service were able to find the cause. I've never been an expert in ColdFusion, Microsoft IIS or Microsoft SQL Server, the platform we chose in 2002 when SportsFilter's founders paid Matt Haughey to develop a sports community weblog inspired by MetaFilter. Haughey puts a phenomenal amount of effort into the user interface of his sites, and web designer Kirk Franklin made a lot of improvements over the years to SportsFilter. Users liked the way the site worked and didn't want to lose that interface. After I cobbled together a site using the same code as the Drudge Retort, SportsFilter's longtime users kept grasping for a delicate way to tell me that my design sucked big rocks.

PHP's a handy language for simple web programming, but when you get into more complex projects or work in a team, it can be difficult to create something that's easy to maintain. The ability to embed PHP code in web pages also makes it hard to hand off pages to web designers who are not programmers.

I thought about switching to Ruby on Rails and bought some books towards that end, but I didn't want to watch SportsFilter regulars drift away while I spent a couple months learning a new programming language and web framework.

During the Festivus holidays, after the family gathered around a pole and aired our grievances, I found a way to recode SportsFilter while retaining the existing design. The Smarty template engine makes it much easier to create a PHP web site that enables programmers and web designers to work together without messing up each other's work.

Smarty works by letting web designers create templates for web pages that contain three things: HTML markup, functions that control how information is displayed, and simple foreach and if-else commands written in Smarty's template language instead of PHP. Here's the template that display SportsFilter's RSS feed:

<?xml version="1.0" encoding="ISO-8859-1"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
  <channel>
    <title>SportsFilter</title>
    <link>http://www.sportsfilter.com/</link>
    <description>Sports community weblog with {$member_count} members.</description>
    <docs>http://www.rssboard.org/rss-specification</docs>
    <atom:link rel="self" href="http://feeds.sportsfilter.com/sportsfilter" type="application/rss+xml" />
{foreach from=$entries item=entry}
    <item>
      <title>{$entry.title|escape:'html'}</title>
      <link>{$entry.permalink}</link>
      <description>{$entry.description|escape:'html'}</description>
      <pubDate>{$entry.timestamp|date_format:"%a, %d %b %Y %H:%M:%S %z"}</pubDate>
      <dc:creator>{$entry.author}</dc:creator>
      <comments>{$entry.permalink}#discuss</comments>
      <guid isPermaLink="false">tag:sportsfilter.com,2002:weblog.{$entry.dex}</guid>
      <category>{$entry.category}</category>
    </item>
{/foreach}
  </channel>
</rss>

The Smarty code in this template is placed within "{" and "}" brackets. The foreach loop pulls rows of weblog entries from the $entries array, storing each one in an $entry array. Elements of the array are displayed when you reference them in the template -- for example, $entry.author displays the username of the entry's author.

The display of variables can be modified by functions that use the "|" pipe operator. The escape function, used in {$entry.title|escape:'html'}, formats characters to properly encode them for use in an XML format such as RSS. (It's actually formatting them as HTML, but that works for this purpose.)

Because Smarty was developed with web applications in mind, there are a lot of built-in functions that make the task easier. SportsFilter displays dates in a lot of different forms. In my old code, I stored each form of a date in a different variable. Here, I just store a date once as a Unix timestamp value and call Smarty's date_format function to determine how it is displayed.

Smarty makes all session variables, cookies, and the request variables from form submissions available to templates. In SportsFilter, usernames are in $smarty.session.username and submitted comments are in $smarty.request.comment. There also are a few standard variables such as $smarty.now, the current time.

To use Smarty templates, you write a PHP script that stores the variables used by the template and then display the template. Here's the script that displays the RSS feed:

// load libraries
require_once('sportsfilter.php');
$spofi = new SportsFilter();

// load data
$entries = $spofi->get_recent_entries("", 15, "sports,");
$member_count = floor($spofi->get_member_count() / 1000) * 1000;

// make data available to templates
$smarty->assign('spofi', $spofi);
$smarty->assign('entries', $entries);
$smarty->assign('page_title', "SportsFilter");
$smarty->assign('member_count', $member_count);

// display output
header("Content-Type: text/xml; charset=ISO-8859-1");
$smarty->display('rss-source.tpl');

Smarty compiles web page templates into PHP code, so if something doesn't work like you expected, you can look under the hood. There's a lot more I could say about Smarty, but I'm starting to confuse myself.

There are two major chores involved in creating a web application in PHP: displaying content on web pages and reading or writing that content from a database. Smarty makes one of them considerably easier and more fun to program. I'm fighting the urge to rewrite every site I've ever created in PHP to use it. That would probably be overkill.

Comments

Nice writeup, rcade. I was leaning towards switching to Smarty for my next project, and I think this post has pushed me over the edge.

FYI, whatever provides the headers and CSS for Workbench seems to be malfunctioning at the moment...

Happy 20th anniversary!
13. Health Opinion
1. Rogers Cadenhead, "Social Insecurity," The Shorthorn, University of Texas, Arlington, TX

I've recently worked with a bunch of PHP apps that use Smarty under the hood-- after a few weeks of it, I liked Smarty a lot more than those apps, but it still feels like half a step to me, like it's designed for someone who sees the value in MVC but doesn't want the rigor. It's better than a sharp stick in the eye, but it's not worth recoding old apps over.

Yay! I noticed you pulled off the herculean task of moving to PHP but the UI was kind of off-putting. Glad to see it brought back inline with the previous design. It looks great and seems to be functioning well!

the UI was kind of off-putting

Word. I'd be really interested to see if there's any statistical backup to my belief the "off-putting" design brought in more trolls & illiterates. Not sure how to quantify that, especially since if there was a drop in page views, it would be hard to separate the design's effect from the lack of new content.

I don't think the design attracted more trolls -- the stopgap relaunch took away the tools Gary uses to keep the site free of them. He's got everything back now except the ability to delete links, which I'm adding tomorrow.

Did you think about maybe using the Symfony framework? I only ask because you mention that you thought about using Ruby On Rails. Of all the PHP frameworks, Symfony works the hardest to be a straight replication of Ruby On Rails. They even found ways to imitate mixins in PHP (using the magic method calls).

I recently was asked to use Symfony for a backend project for AudioLunchbox.com, and I became a big fan. I had, previously, run into the same problem you had - PHP code can easily get out of control on big projects. I was thinking that for future large-scale projects I was going to switch to Ruby On Rails, but Symfony offers enough structure that I think I will stay with PHP.

I should add, I'm wary of Smarty. We used it once for one big project. I found it very, very slow. I'm also uncomfortable using a template language other than PHP. I'm sure you know the argument - PHP is a template language. A template language needs to be written in a base of C. If you write a template language using a script language, the result will be slow.

The counter-argument is suppose to be that designers don't know how to design a template if it has PHP in it. I personally haven't found this to be true. Both with PHP pages, also the templates in Ruby on Rails, designers quickly learn to skip past the blocks of code. One woman said to me "I just read the page as if the code wasn't there."

Even if the argument was true, how would Smarty be an improvement? Replacing one obscure syntax with another obscure syntax doesn't improve things.

One can use logic-less templates, but those are awful for the reasons that I wrote about here:

When your code generates HTML, you rob designers of their ability to innovate

I can't believe you abandoned ColdFusion. I hope you're still benefiting from the expressive power of DOS.

Just becuase something is a bit dated doesn't mean it should be thrown out.

Have you still got your copy of the Radio UserLand book.

My programming these days is limited to trying out various frameworks and langauges... and finding that they don't seem to make me accomplish anything of substance. Still waiting for the key to productivity.

Ohh... shiny... BRB. jParallel...

I didn't abandon ColdFusion because it was inferior to PHP. I did it because I could never find the time to learn ColdFusion development on Windows/IIS/Microsoft SQL as well as I've learned PHP development on Linux/Apache/MySQL.

Rogers

Yes, I understand the idea that a platform is an investment in time. Mastery of a software stack requires a lot of time to develop and maintain.

ColdFusion is a viable commercial platform but there's a lot of great FOSS software that allows the small commercial developer to make a living.

Keep writing about the tools you find worthy of your time and mind-investment.

thanks this is interesting article very useful

Add a Comment

All comments are moderated before publication. These HTML tags are permitted: <p>, <b>, <i>, <a>, and <blockquote>. This site is protected by reCAPTCHA (for which the Google Privacy Policy and Terms of Service apply).