DOM vs. Template

Fredrik Holmström recently posted a small template engine, based on DOM-manipulation. While there are certainly a lot of template engines around, I find this approach interesting. The concept is simple enough; The template is parsed into an object model (DOM), and then values can be assigned to these through PHP code. The main difference to traditional template engines (Such as Smarty), is that the template it self doesn’t have any imperatives within. In fact, the template doesn’t even have to be written to the template engine, to be used – Any markup can be used as a source.

Since the template can’t contain any view-logic, it ends up in a separate place (In PHP code). This makes the separation between presentation and logic airtight, which was the main idea of template engines in the first place. Another benefit is that since there is no string-level manipulation, it is virtually impossible to inadvertently get injections-type security breaches.

The template may be unaware of the view-logic, but the opposite can’t be said. To bind values to the template, the view-logic needs to be aware of the internal structure of the template. This means that if the template changes, so must the view-logic. To decouple this dependency, we need some kind of abstraction.

Luckily it just so happens that there is a very convenient mechanism for that; Element id‘s can be used to address central nodes in the markup. They do however have the rather annoying limitation (For this use), that they must be globally unique to the document. A better candidate then, is to use classes (The HTML attribute – I’m not talking of PHP classes) to address elements.

The really nice thing about using classes is that it’s very unobtrusive to the markup. One will have to add classes, but since they would have to go on central elements in the markup, they would be prime candidates for reusing as fix points for CSS rules and for Javascript code. Instead of being superfluous markers in the HTML code, they actively help to write better markup.

That sounds good in theory, so to see how it holds out in reality, I mocked together a small prototype. Even with a very limited API, it has a remarkably good expressiveness:

Simple variable binding


$t = new Domling('<p class="hello"></p>');
$t->capture('hello')->bind("Hello World");
echo $t->render();

<p class="hello">Hello World</p>

Switching a block out


$t = new Domling('<p>Lorem Ipsum</p><p class="message">Hidden message</p>');
$t->capture('message');
echo $t->render();

<p>Lorem Ipsum</p>

Putting it back in


$t = new Domling('<p>Lorem Ipsum</p><p class="message">Hidden message</p>');
$block = $t->capture('message');
$block->bind();
echo $t->render();

<p>Lorem Ipsum</p>
<p class="message">Hidden message</p>

And looping over a block


$t = new Domling('<ul class="links"><li class="link"><a class="anchor" href="#">title</a></li></ul>');
$links = array(
  'Sitepoint' => 'http://www.sitepoint.com',
  'Example' => 'http://www.example.org?foo=bar&ding=dong');
foreach ($links as $title => $link) {
  $t->sequence('link', 'links')->bind(array('anchor:href' => $link, 'anchor' => $title));
}
echo $t->render();

<ul class="links">
<li class="link"><a class="anchor" href="http://www.sitepoint.com">Sitepoint</a></li>
<li class="link"><a class="anchor" href="http://www.example.org?foo=bar&amp;ding=dong">Example</a></li>
</ul>

If you’re curious, you can get the full source code for the above examples from here: http://php.pastebin.com/f76ba8d70

But please mind that this is just a proof-of-concept; There are probably a few quirks that should be ironed out before this could be used in production.

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • romrom

    hi there,
    there is a MVC framework that uses DOM and which implemented the jQuery API.
    but the project is very youth and the documentation is still only in french
    http://sloth-project.org

  • http://www.fredrik-holmstrom.se thr

    Hi!

    I (even more) recently posted an updated version of the pQuery library that allows you to keep the presentation generation code and the presentation markup in the same file, here’s the post: http://loveandtheft.org/2008/09/20/php-templating-in-53/

    I still relies on the DOM-structure, meaning you’ll be doing something like: $root->li->something = "Something else"; But I have a local development version that is complete with a CSS selector, so you techincally can do this instead: $root("#post-list li")->title = "My title for something"; which puts an abstraction layer in form of dom #id’s and css-classes allowing you to move them around (in effect changing where the output gets pushed into the template without changing the php attached to it).

    / Fredrik Holmström

  • p.vernooij

    I’ve created something similar like this, since i really liked the way i could manipulate the DOM in JavaScript. Why not in PHP?

    I’ve used XPATH queries to select elements where content should be injected. ID’s are also supported.

    The main advantage is the HTML prototypes produced by web designers are actually usable and can even be maintained by the same people during production, without the need of any php knowledge.

  • Josh

    The main advantage is the HTML prototypes produced by web designers are actually usable and can even be maintained by the same people during production, without the need of any php knowledge.

    Designers around the world will undoubtedly rejoice. Finally creating templates wil be p*** easy for those hallowed and somewhat mythical creative types who are masters in the dark arts of CSS and HTML/XHTML standards with which they regularly transform simple paragraphs and headers into veritable disneyland like user interfaces, nonchalantly float divs with pinpoint accuracy through the gauntlet of CSS positioning, bestow their Utopian semantic vision upon us with weighty intellectual authority, but somehow lack the mental capacity or nous to handle a couple of echo statements.

  • uhh

    XSL anyone?

  • Godar

    We just released a PHP DOM Template Engine at http://www.domtemplate.com it uses three tags var,choice and repeat to access a standard XHTML document. It works well in an object environment and is easy for a designer to understand so they can build templates for an application as well.

    Its aim is to ensure designers can work in along side the developers.

  • Troels Knak-Nielsen

    @thr
    That sounds interesting. I kind of like the prospect of only allowing access through classes (And perhaps id’s), because it forces one to use the abstracted accessors. That way you are reasonably sure that you can replace the template later on. I wonder how such a strict strategy would stack up in practice, though.

    @uhh
    XLS solves a different problem really. And quite frankly, I think that it is a good example of over-engineering.

    @Godar
    I took a short look at your project. I see that you use non-standard attributes in the HTML. Is there any reason not to use class or id?

  • Godar

    @Troels
    First, Thanks for having look at the project ;-)

    There is really no need to use standard attributes in the template source files as long as it conforms to the XML standards. Those attributes are removed at render time and do not get rendered to the browser anyway. There could be an argument to use namespacing but for now it seems to work ok without all that over-complication.

    The main aim was to produce a template language that a designer could learn fast then create/maintain templates for the developer with minimal developer consultation.

    With the three tag language it is easy to explain how things work:

    * VAR: text and attribute values are replaced
    * CHOICE: Element blocks are shown or hidden
    * REPEAT: Used for all repeating data (tables. lists, results, etc)

  • Ren

    Is there any reason not to use class or id?

    After some tinkering, it’s possible, but not sure its desirable.

    Would have a quicker template engine if it didn’t have to look up template variables for every class or id it sees.

    The tinkering code is at http://homepage.ntlworld.com/jared.williams/php/template.php

    2 classes, TemplateCompiler which compiles a html template down to a Template instance which could be cached to save the XML parsing/processing.

    Several limitations in the implementation, like no attribute values can be changed (due to limitations in XmlWriter)