vBulletin 4.0 Template Syntax


New Member
With the style changes going into vBulletin 4.0 it is the ideal time to change the template syntax being used. The original syntax in vBulletin 3 is no longer supported and suitable replacements and enhancements have been added.

The first thing that has been removed is eval, before in vBulletin 3 you would find eval used everytime a template would be evaluated, this however has potential security implications and an overhead associated with it since none of the templates could be stored by opcode caches like APC and XCache.

vBulletin 4 now requires variables to be registered prior to their use within templates, previously all variables available at the time the template was rendered were available but this was known to cause problems when a variable was overwritten or not available.

The new code to render a template looks similar to below, while this may seem very verbose the registration method will allow more optimizations to be performed in the future.

            $templater = vB_Template::create('forumhome_event');
                $templater->register('callink', $callink);
                $templater->register('daysevents', $daysevents);
                $templater->register('eventdate', $eventdate);
                $templater->register('eventdates', $eventdates);
            $upcomingevents = $templater->render();

The templates themselves also use a new syntax themselves, these have been namespaced for performance reasons. During scanning we only need to look at tags that have the vb namespace. Due to the way the scanner is written to provide a new tag syntax a class has to be dropped in with a validate and compile method defined.

<vb:if condition="$var == 2">
Value is 2
<vb:elseif condition="$var == 3">
Value is 3
<vb:else />
Value is {$var}

So as you can see we've added an elseif condition to templates, another commonly requested feature was a loop.

<vb:each from="$myarray" value="foo">
Hi {$foo}

For content that helps describe the value of a template but has little use in being in the output we can use the new comment tag, when the templates are compiled these will be left out of the output. This can potentially help save in bandwidth.

<div class="someclass">
Output: Test
This won't be printed as comments are stripped at compile time.

For the cases in which we wish to print literal text and do no variable evaluation or tag parsing we can use the literal tag, everything will be printed exactly as it is within the tags.

<vb:if condition="$var == 'test'">
Some test

In addition to the new tag syntax, we've also introduced a short hand curly syntax for simpler actions and some output formatting on variables. This moves the requirement to do formatting within the code to the template layer.

Dates can be formatted based on a timestamp, the second parameter indicates the format, if left blank the default board format is used.

{vb:date $var}
{vb:date $var, Z}
{vb:time $var}
{vb:time H:i}

There is also a shorter if condition, when you only want a simple if, else.

{vb:if 1+1 == 2, 'It does make 2', 'Ooops, maths fail!'}

Number formatting

{vb:number 1000.1234, 3}

In an attempt to reduce the likelihood of XSS attacks there is now the concept of raw phrases and raw variables, anything without the raw prefix will automatically be escaped with htmlspecialchars_uni() before being evaluated.

{vb:phrase phrasename, $var, '<script>alert(document.cookie);'}
{vb:rawphrase phrasename, $var, '<script>alert(document.cookie);'}

The second example here will execute javascript, the first will print the escaped text.

For variable access we have the regular kind, the raw variables and finally a short hand method.

{vb:var username}

he above two curlys will provide the exact same output, the latter being a little less verbose.

Finally to complete the new syntax we are now offering more detailed error messages, when an invalid syntax is used we can tell the user what line this occurred and what was malformed.