Sean Middleditch » 2007 » May

Released php-sugar 0.50. The HTML caching is complete, and we even have multiple storage driver support now.

I think I’m just about ready to call this thing Done(tm). The only feature that Smarty has that Sugar doesn’t is the ability to define new block types, but I’m not sure how much we really need those. The foreach loop handles most cases. I can maybe see a use-case for a no-cache block, and for a second type of loop, although I think that adding a range type and iterator would solve that.

For the range thing, I’m thinking a syntax like this could be quite useful:

1..10
-5..20
10..-10
0..$i
0..($i-1)

Put that in a foreach loop and we’re golden:

<% foreach $i in 1..10 %>

That and the regular usage would account for pretty much every type of loop I think you’d need in a template language. Maybe a while loop would still come in handy though.

A no-cache block would need compiler support, so allowing custom blocks isn’t necessary for that, and I might add it anyway. I really don’t see the need for other types of blocks.

Anyways, I’m pretty pleased with how PHP-Sugar has turned out.

Here it is:

http://code.google.com/p/php-sugar/

Current version is 0.20. There are only a small handful of missing features.

I’ve been pretty dissatisfied with Smarty. I use it for a lot of projects, and I’ve come into a number of serious short comings which its design. Really, though, there are two major facts that make Smarty a horrendous system to work with:

(a) the regex-based parser isn’t flexible enough to do what programmers expect out of a language

(b) the syntax is over-complex and non-obvious and thus confusing for non-programmers, i.e., the designers

If the template system is too inflexible for programmers and too difficult for designers, there’s a serious freakin’ problem with the template system.

I’ve spent the last two days writing a new template system for PHP. One much, much different than any of the other template systems out there for PHP. The main thing going for PHP-Sugar is that the compiler is using an actual compiler framework. The only regex used is the token matcher. There’s even a hand-written LR grammar in there for parsing expressions.

The language handles variables, assignments, if/elif/else statements, function calls, foreach loops, and expressions. It has a compilation cache that uses a plugable interface so the default file-based backend can be replaced with a DB backend or whatever else the application developer needs.

Oh, all variable output is HTML-escaped by default, which means that - unlike both PHP and Smarty - programmers/designers no longer to in more effort to be secure than to be insecure. HTML/JavaScript injection attacks and XSS are really common, and languages with no thought applied to ease of use like PHP/Smarty are, I think, the biggest cause of these kinds of attacks. PHP-Sugar will aid greatly in keeping apps secure.

The codebase has taken well under two days to write (I’m thinking about 16 man hours so far). The code is only 793 lines, including blank lines and comments. There are only a few missing features at this point. The big ones are the ability to use PHP objects (not hard to add), a second-level HTML cache like Smarty has (PHP-Sugar only has the compilation cache right now), and a second flexible loop type that allows C-like for loops or while loops. The cache will be the most difficult part, but I’m quite confident I can get that done in no time. I think PHP-Sugar will easily come in under 1000 lines of code, before I start puffing up the comments with PHPDoc comments all over. Compare this to Smarty, which is ~4700 lines. Even if you assume docs take up 50% of that, that’s still huge in comparison. And PHP-Sugar is easier to use, far more flexible, and safer.

There is one thing that Smarty excels at compared to PHP-Sugar, and that’s raw speed. Smarty compiles down to PHP code and lets the Zend engine do all the heavy lifting of executing templates. PHP-Sugar instead uses simple custom stack-based VM that executes instructions stored in an array. The compile cache just uses serialize/unserialize for storing the code. I might change this. Right now, PHP-Sugar compiles directly to its bytecode instead of building an AST - if I convert to using an AST, which would help doing simple optimizations, then I could replace the compiler and runtime with pluggable interfaces and put in a direct-to-PHP one for people who feel that they need the extra speed.

I’m hoping to push this out to the public soon - possibly into PEAR, if I motivate myself to do the various minor modifications necessary to meet their coding guidelines and other requirements for being added to the repository - and letting people play with it. I’m going to push it into production use on a new site tomorrow and get initial designer feedback and stress testing.