PHP Constants in Smarty

2010-01-12

Smarty is a good templating system. In my experience it lacks a bit of customizability, but so far I have been able to hold back on the urge of hacking it to do what I want.

Specifically, I wanted to be able to use constants. The default syntax for using constants in Smarty is:

Code: (PHP Smarty)

{$smarty.const.YOUR_DEFINE_HERE}

And my preferred version would be:

Code: (Custom Smarty)

{#YOUR_DEFINE_HERE}

It's shorter, less bloated and thus easier to read. This is not easy to make, yet not impossible to accomplish. Let me show you how to do it in Smarty2:

There are a few ways to plug into the Smarty system. Ideally I would've liked a way to convert just the smart interpreted parts of the template and convert my own syntax to the Smarty compatible one (replacing {#LANG_SUBMIT} by {$smarty.const.LANG_SUBMIT} and being done with it). This is not possible. However, you are able to plug into the precompiling "event". You can add your own functions and you can do some other stuff that, eventually, was useless in this case.

I start with a precompiled function to replace the # into a custom function I define later. The custom function simply takes one argument and returns the value of the defined constant (at runtime, that way I can still change the language constant in the database without having to recompile all the Smarty templates).

First the prefilter function:

Code: (PHP)

function preFilterConstants($strInput, $objSmarty) {
return str_replace('{#', '{constant c=', $strInput);
}

Make sure to replace '{' by whatever character you use (I use the backtick ` in my code because curly braces tend to screw stuff up).

And the custom function:

Code: (PHP)

function functionHash($args, $objSmarty=false) {
$c = $args['c'];
if (defined($c)) return constant($c); // would throw an error if constant was not (yet) defined
return $c; // default behaviour
}

Hook it up to the Smarty system:

Code: (PHP)

$objSmarty->register_prefilter('preFilterConstants');

$objSmarty->register_function('constant', 'functionHash');

And you're done! Your Smarty object can now parse {#STUFF} properly. Note that you incur some overhead because of the limitations Smarty imposes with these hacks. The only caveat is that all the instances of {# will be translated, but there won't be many of those in most templates :)

I would like to see an easier way of plugging into Smarty. Surely it's not that difficult of allowing easy access when you already have the parsing system in place?

Maybe Smarty3 will make it easier. Alas I don't have the time to wait for that to finalize in my current project.

Hope it helps you!