Showing posts with label templates. Show all posts
Showing posts with label templates. Show all posts

Sunday, 4 May 2008

Using XSLTs as a template engine in Zend

I've been working my way through a book that is using the Zend framework to do—buzzword approaching—"Web 2.0" stuff, and it started to mention the Smarty template engine. It seems the author, as well as many other PHP developers love this silly template engine stuff made up placemarker tags. Whereas I'm sure Smarty has lots of really cool features which would make my life a lot easier, I really couldn't be bother to learn how it works, and figure out what it needs from me so that it does just that. I seem to prefer the idea of my application models spitting out well-formed XML and using XSLT to style this to whatever template style I want to use later on.

I don't know why I like the idea so much. I think it's the extent to which the model doesn't care how the data is rendered, it's job is just to deliver it and it does that through XML. There is of course a parsing delay involved in doing transforms and I'm going to try to get some data or results of my own to try and analyse that, but for the time being I'm happy. There's even the possibility of processing the document client-side by either delivering pure XML with a stylesheet declaration, or using a javascript library like Sarissa and falling back to server-side transforms onlyZend to do XSLT transform instead of rendering templates and it's just about working. But it's led me to thinking about the bigger picture. XSLT allows us to include multiple stylesheets in one document by using expressions such as import and include. So why can't we make a master XSLT template file which doesn't transform any XML itself, but simply matches the document root to apply its template only once, but then crucially providing a placeholder for an imported stylesheet in the right place. This would allow me to use it as a 'master view' which is combined with the view my controller action renders.

There is however, a few problems. Whereas now my view renders whatever XML its passed using a single stylesheet, it now has to use the master stylesheet, but the master itself has to be aware of which view-specific stylesheet to include. This is getting a bit too much like a template language – replacing strings in the master template file with a path to the view specific stylesheet, and that's what I'm trying to avoid. The other problem is with CSS. Putting persistant navigation in the master stylesheet is fine, but what happens when you want to change the CSS class of one of the link elements? You have no hook to the master from the view specific stylesheet. I thought about having the navigation as its own XML file – easily editable and adaptable. Then view scripts can be used to change that nav XML, marking which link should have a CSS class of "current" and combining it with any data XML the view has received assuming there and some mechanisms are in place for the master stylesheet to find those flags, and produce the right XHTML output. Perhaps xml namespaces are the right way to go here, in order to differentiate between nav and content XML. Ideally, minimising the number of transforms is a good idea, so I don't want to have to transform the nav XML data, then use another template to transform that result to the final output including the actual content. The content XML and nav XML could be combined just before XSLT processing. It would be simple to wrap content XML from the model with persistent data. But the problem still remains to tell the master stylesheet which view specific stylesheet to include in order to render it correctly.

Javascript may be an alternative. Client-side transforms has the nice quirk of sorting through XSLT which is really neat, but Javascript is so horrible to code with. I have to think about it more.

Thursday, 20 March 2008

Smarty: A PHP template Engine

Ok Smarty. All you really need is everything in the libs/ directory. When copying in unix, remember to add option -r to go into the internals/ and plugins/ directories within libs/. With those files saved somewhere, your PHP has to find one file in particular-Smarty.class.php (they also seem to be quite strict about the capital "S" in "Smarty"). That file needs to be referenced with an absolute path. This can be done a number of ways, look them up at Smarty's documentation. One cool way I've found so far is this:

// Use the absolute path for Smarty.class.php
$base_path= basename(dirname(__FILE__));
require($base_path.'/Smarty/Smarty.class.php');

Of course this assumes that you're writing this in a file which is in the document root of your webserver, and that the Smarty files are located further down in the folder Smarty/. The require_once is similar to PHP's include statement apart from it will result in an error if it can't find the file (include will just try and not care if it can't) and the _once part ensures there's no errors if you accidentally try to require it again.

Within that Smarty directory, make four folders: templates, templates_c, cache and configs. Link these files up with your code with

$smarty = new Smarty();
$smarty->template_dir = $base_path.'Smarty/templates';
$smarty->compile_dir = $base_path.'Smarty/templates_c';
$smarty->cache_dir = $base_path.'Smarty/cache';
$smarty->config_dir = $base_path.'Smarty/configs';

Put this immediately after the required_once statement. Then start making templates and go.