John Resign created some incredibly wonderful Javascript code for templating. It’s so terse that it almost shouldn’t work…but it does. I’ve been using it on a lot of front-end JS apps lately, and realized I could make a few changes and improvements.

First off, I don’t like <% asp style tags %>. It reminds me of programming ASP. It reminds me of a trip through hell I’ve taken too many times. I changed it to use PHP-style tags instead:

<ul class="<?=myclass?>">
<? for(var i = 0; i < items.length; i++) { ?>
    <li><?=items[i].name?>
<? } ?>
</ul>

This makes it easier for me to type. I also made one further modification. Adding $ in front of your variables will check if they are undefined before using them, and if not defined will return them as null:

Hello, <?=$name?>.
<? if($user.friends) { ?>
    You have <?=$user.friends.length?> friends.
<? } ?>

The if statement above will compile to

if((typeof(user.friends) == 'undefined' ? null : user.friends)) { ... 

This allows some simple usages of undefined variables, such as “if(undefined_var) { … } else { … }” which actually pops up a lot. You still can’t access non-existent properties of variables that aren’t defined, but this should catch a lot of errors that would otherwise turn your code into a bunch of if(typeof …)’s.

Here’s the code (for brevity, I left out all the caching stuff that makes this fast):

var template = '<h1>My Template</h1> ...';
new Function(
	"obj",
	"var p=[],print=function(){p.push.apply(p,arguments);};" +
	// Introduce the data as local variables using with(){}
	"with(obj) {p.push('" +
	// Convert the template into pure JavaScript
	template.replace(/[\r\t\n]/g, " ")
		// find any code blocks (not html, not <?=print_var?>... anything inside a
		// <? ... ?>
		.replace(/<\?(.*?)\?>/g, function(match) {
			// look for any string starting with a "$" and wrap it in a ternary typeof op
			return match.replace(/\$([a-z_][a-z0-9_\.]+)/gi, '(typeof($1) == "undefined" ? null : $1)');
		})
		.split("<?").join("\t")
		.replace(/((^|\?>)[^\t]*)'/g, "$1\r")
		.replace(/\t=\$?(.*?)\?>/g, "',(typeof($1) != 'undefined' ? $1 : ''),'")
		.split("\t").join("');")
		.split("?>").join("p.push('")
		.split("\r").join("\\'") + "');}"
		//+ "console.log('Loading template " + name + "');"
		+ "return p.join('');"
);

This has been working for me for a bit now, and has saved me countless annoying declarations at the top if my templates. If you run into any problems, please let me know.

Smarty is everyone’s favorite templating language for PHP. It’s great in many ways, one of the main features being that it can display things on a website. It also promotes separation of display code and logic, which many PHP programmers seem to have trouble with: oscommerce, PHPList, etc etc.

So why do I hate it?

<rant>
There’s no fucking point! All bad programmers write bad code. Why create a language within a language just to force bad programmers to do one thing right? I realize that Smarty does enforce separation of logic from display very well. I’ve used it in several projects. But if its capabilities are so strikingly similar to PHP that for most things there is a 1-1 reference, why bother? Why not just use PHP code?

Also, the plugins (and {php} tag) allow you to make logical decisions, run mysql queries, send rockets to the moon…there’s nothing you can do in PHP that you cannot do in Smarty…which makes Smarty completely worthless for what it’s trying to do.

If you want to promote good programming, you don’t need Smarty. You can rewrite Smarty as a PHP object that sets variables and includes a template. I’ve written this a dozen times over…and it does the exact same thing, except templates are in PHP so everyone can understand them, there is no caching trickery going on, and best of all you don’t need to reference some stupid guide on how to display something in a strange language which you already know how to do in PHP.
</rant>

So, in summation, please don’t stop using Smarty. It’s a good piece of code for people who don’t understand the basics of separation of logic from display…but realize that Smarty is a hack, a patch, a band-aid. The REAL problem is bad programming, not something inherently wrong with PHP that needs to be rewritten.