New thread - Template base class design
| From: | Greg Beaver | Date: | Fri, 11 Jun 2004 02:22:14 +0000 |
| Subject: | New thread - Template base class design | ||
| Groups: | php.pear.dev | ||
| Request: | Send a blank email to pear-dev+get-30460@lists.php.net to get a copy of this message | ||
We need a new thread
Paul M Jones wrote:
<?php // data for the template $data = new StdClass; $data->text = 'xxxx'; // instead of 3 lines in "normal" Flexy... $template = new HTML_Template_Flexy(); $template->compiler('/name/of/template.html'); $template->outputObject($data,$elements) // or 3 lines in "normal" Savant... $Savant =& new Savant(); $Savant->assign('t', $data); $Savant->display('/name/of/template.html'); // use 5 lines for Common Jausions Interface template system. $tpl =& new Template(); $tpl->compiler =& new Template_Compiler_Flexy(); $tpl->openTemplate('/name/of/template.html'); $tpl->setData('t', $data); $tpl->output(); // the compiler is swappable.This is highly unlikely to be necessary in the same script, but could be supported much more elegantly.
$tpl =& new Template(); $tpl->compiler =& new Template_Compiler_Savant(); $tpl->openTemplate('/name/of/template.html'); $tpl->setData('t', $data); $tpl->output();I would suggest something like: <?php $tpl = &Template::create('flexy'); $tpl->open('/name/of/template.html'); // or, $tpl->open($fp) - let it accept a file handle as well, // so that custom streams can be used, for both input filtering // and unusual filesystems $tpl->configure([template-specific data, in an associative array]); $tpl->set('t', $data); $tpl->output(); // or $res = $tpl->toString(); $tpl = &$tpl->create('savant'); // or $morecontrol = new Template_Foo; $morecontrol->doSomethingSpecialForFoo(); // initialize a new template from an existing sub-template $tpl = &$tpl->create($morecontrol); // etc. ?> The advantage of this design is that the user can use the pre-built templates, or pass in a custom one to leverage the code in the base class, as long as it conforms to the API expected of child classes. I would recommend that the assignment question be studied very carefully - Alan's method solves the extract() problem elegantly. If template variable assignment simply meant <?php $tpl = &Template::create('flexy'); $tpl->t = $data; $tpl->thing = &$refdata; ?> and the template in savant would simply reference $this->t and $this->thing. Other templates would compile so that {t} became $this->t, and so on. This would allow very straightforward management. It would mean that ALL private/protected variables would have to be prefaced with _ to avoid overwriting, but that's not a big deal. resetting template variables would be as simple as: foreach (get_object_vars($this) as $name => $val) {
if ($name{0} == '_') {
continue;
}
unset($this->$name);
}
and could be included to allow re-using a template. Implementing blocks would be very easy with this method, by instantiating a number of templates and adding them as template variables
$tpl = &Template::create('IT');
$block = &$tpl->create('IT');
$block->var1 = 1;
$block->var2 = 'hi';
$block->open('/path/to/block.php', 'blockname');
// optional parameter only recognized by IT, ignored by others
$tpl->block1 = &$block;
$tpl->open('/path/to/block.php', 'main');
This would be IT-specific and so obviously require a slight rewrite to work with a switch to another template style. One solution might be to do some magic.
$tpl->open('/path/to/block.php\\main');
The basic open code would normalize all directory separators, but IT could split on the backslash, to determine which block is needed. When switching to another template, this would try to open the file "main" - it would result in an interesting directory structure, but could work.
In any case, the important thing is direct assignment to members of the template is probably the way to go - it's efficient, direct, and really easy to document.
In PHP5, __set() could be used to validate template assignment as well, which is a neat by-product of this design choice.
Greg