...

View Full Version : Suggestions for class based template engine



thesavior
03-17-2007, 04:49 AM
Im interested in finding the best method for a template system. I wan to have the engine as a class, and all the templates will be in tpl files. Does anyone have any ideas on how to do variables, parse things, etc. Im looking for ideas.

Inigoesdr
03-17-2007, 07:18 AM
Just use Smarty (http://smarty.php.net/).

Fou-Lu
03-17-2007, 07:24 AM
Template classes are IMO the best route to go. Reading from files is fine as well, though not quite as secure (depending on your methods) as users can directly access the template directory unless its above your root. Chances are that will not be a problem however.
To start, parse variables using an eval (http://ca3.php.net/manual/en/function.eval.php) function. This allows you to parse and store variables if desired. Eval does not print output to the screen so you will need to handle that as well.
Next, beware of a common pitfall: escaping. Assuming that your .tpl file is nothing more than html with php variables, ie:


// Yeah I know I'm too lazy to declare
<html>
<head>
<title>$pageTitle</title>
</head>
<body>
...
</body>
</html>

or something of the sorts (note that you do not need to declare any html, head or body wrappers except on your 'shell' based templates). Just run an addslashes after reading before evaling.
Skeleton code would probably look like so:


public class TemplateHandler
{
public static function fetchTemplate($templateName = '');
public static function printTemplate($templateName = '');
private static function parseTemplate($templateName = '';
}

Where fetchTemplate opens and stores the requested template, printTemplate, well prints it (uses the fetchTemplate), and parseTemplate evaluates the code as php.
As you can see this is a static class and does not need an instantiation. You can create a TemplateHandler object if you want (Template->fetchTemplate()) or keep it static (TemplateHandler::fetchTemplate()). For php 4.x compatability, drop any public/privates and static declarations, and do keep in mind to not refer back to it as an object at any time if you want to keep it as a static method. This is really your choice. The above code is more of an abstract / interface class, but it will give you an idea.
You may want to add more to it too, to update the templates and read the actual data without parsing. All easily added into the class
Hope that gives you an idea!

thesavior
03-17-2007, 07:43 AM
The thing is, im planning on coding my own, but the issue im having is visualizing how to get everything to come together. Thats why i need ideas of how i should make it work, not links to actual scripts. The template files have to be outside of php for this script btw.

firepages
03-17-2007, 12:31 PM
well if it helps, my template is a single class which handles standard placeholders IF's and simple loops (no nested loops) it is called and constructed with the template..



<?php
include_once LIB.'/lib/std_tpl_parser.class.php';
$yaks = new std_tpl_parser(TPL_PATH.'/tplname.tpl');

//grab and set the standard replacements
$static=array($db->fetch("SELECT * FROM table WHERE id=$id"));
$yaks->set_static_data($static);

//an iterator, there can be several in a template but not nested
while($row=$db->fetch("SELECT id,name,blah FROM table")){
$its[]=$row;
}
$yaks->set_iterator_data('MAIN'=>$its);
return $yaks->parse();
?>


I use {REPLACE_THIS} for normal replacements (replaced from the $static associative array)
and
{{ITERATE=ITER_NAME}
{ID},{NAME},{BLAH}<br />
{/ITERATE}}

I also allow for {INCLUDE=filename} etc and some other framework specific replacements...

As for the how its sadly all down to regex, in my implementation I pre-parse the iterators and then the standard replacers from the template file all in the constructor...


<?php
class templater{
function templater($tpl){
$this->tpl=file_get_contents($tpl);
$this->iterators[]=$this->parse_iterators();
$this->includes[]=$this->parse_includes();
$this->static_vars[]=$this->parse_static();
$this->static_vars[]=$this->parse_constants();
}

function iterators(){
//regex to find and store all of the {{ITERATE=*}{/ITERATE}} stuff
}
function static_vars(){
//regex to find and store all the {VARS} in the template
}
//etc
}
?>


then the calls to set_static_data and set_iterator_data will store the replacement data ready for the parse() call which sticks it all together

I found that it was important to remove the iterated content and the included content from the template before parsing for static vars.

Pre-parsing the template itself to extract placeholders seemed OTT but it does allow for extras like checking that a template has all the required placeholders before moving any further.

Sadly my regex is shocking ;) and I have yet to implement any template-engine level caching but that is the plan.

I did not use smarty or similar because I wanted something lightweight, did not want to create my own language within PHP etc since PHP IS a templating engine ;) ... but I do regret not adding an ELSE option which I will do when I try again!

thesavior
03-17-2007, 05:46 PM
can you post your entire templater class for me to work off of?

thesavior
03-18-2007, 05:54 PM
*bump*



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum