Beyond The Template Engine

I like the idea of it caching the templates except the function is failing…I get the error

Unable to write cache.

This is a nice article.

This is a great class!
I have used it for one year.
100% PHP is less difficult than learn PHP + Smarty template logic.
Overall, caching works perfect!

Can anyone help with the error I am getting?

Unable to write cache.

If you have PHP5 access, just use an XSL template. 100% better than any other solution I’ve seen. Make yourself a “Writer” calss and a “Reporter” class. Pass the writer around your PHP code which records a DomDocument with all the info which needs to be on your page, then make a reporter which converts the XML output from your app (stored in the writer) and with a bit of XSL magic turn it into XHTML. The PHP code for the templating itself (in the reporter) is only about 4 lines of code! And you get total separtaion of presentation logic and otherwise, because of the intermediate XML (cachable) data stage. Any you want caching? Just write a CachingReporter based on any caching system you care to use. Easy!

Douglas

Hey, can you post example code of all of the classes you are talking about?

-matt

It isn’t all that complicated. The code for a basic Reporter is straight from the PHP.net docs, and the Writer just looks after adding all the text into a string. I’m going to expand the Writer class so that I can send it “real” XML fragments. My app is still in development, so I’ve not needed caching, though it should be easy enough to add to either the Reporter or the Writer class.

Usage

$Writer = new Writer;
$Writer.writeObject($Page);
$Writer.run(new Reporter);

In my application, there is a $State object passed to the Reporter constructor which tells it which template to use. XSL can include other XSL files in the XSL itself, so you don’t need to worry about things like that in the PHP code.

Writer

class Writer {
	
	protected $output;
	
	public function __construct() {
		$this->output = '';
	}
	
	public function run($Reporter) {
		
		$xml  = '<root>' . $this->output . '</root>';
		
		$xmlDoc = new DomDocument('1.0');
		$xmlDoc->LoadXML($xml);
		
		echo $Reporter->report($xmlDoc);
	}
	
	public function writeString($string) {
		$this->output .= $string;
	}
	
	public function writeObject(Writeable $object) {
		$object->write($this);
	}
}

Reporter

class Reporter {
	
	function report($xml) {
		$xsl = new DomDocument;
		$xsl->load('template.xsl');
		
		$proc = new XSLTProcessor;
		$proc->importStyleSheet($xsl);
		
		return $proc->transformToXML($xml);
	}
	
}

The advantage of splitting the reporter and the writer, is that I have a second reporter which simply outputs the raw XML for debugging, then I can swap to the “real” reporter when working on the templates themselves.

(I’m not actually correct calling XSL a templating system, it is a “Transform View” instead of a “Template View”. I find the “Transform View” pattern to be the more powerful solution.)

Douglas

I am having a hard time figuring out how to do something like this:

There will always be a navigation block called “Community” that all users will see. If a user is logged in, I have to show a “Community” navigation block, and a “My Account” navigation block.

I’m trying to find an efficient way to add navigation blocks.

what’s wrong with

<code>
<?php
$pv= array(
‘name’=> ‘John Doe’,
‘email’ => ‘john@doe.com’,
‘password’ => ‘donottell’,
)
include(‘page.tpl.php’);

?>

/// this is what page.tpl.php looks like
<table cellpadding=“3” border=“0” cellspacing=“1”>
<tr>
<td>Name</td>
<td><?=$pv[‘name’];?></td>
</tr>
<tr>
<td>Email</td>
<td><?=$pv[‘email’];?></td>
</tr>
<tr>
<td>Password</td>
<td><?=$pv[‘password’];?></td>
</tr>
</table>

</code>

Ha ha, I wrote that!

its first time i am here…
now days i am looking for some good template engine.

http://mannan.zabvision.edu.pk

Hi,

your template is very interesting and useful. However, can it handle urls like this: index.php?param=1 ?

fetch() method crashes because it expects a file. How to overcome this? Use something like this?

$param=1;
$tpl->set_vars($param);

Thanks for your prompt reply.

Regards,

John.

I have one question on the cache time out. In the example file caching.php it is set to 900. What unit is it - seconds, minutes?

Here´s the code:

$cache_id = $file . $_SERVER['REQUEST_URI'];
$tpl = & new CachedTemplate($path, $cache_id, 900);

from the article:

This script assumes your cache files will go in ./cache/, so you must create that directory and chmod it so the Web server can write to it.

Its 900 Seconds which is equivalent to 15 minutes

hmm, I think I´m far away of separation of business and presentation logic. It´s much faster and easier to do something like the following code directly in the template file.

  <select name="category">
    <option value="0">bitte auswählen</option>
<?php 
while ($row = mysql_fetch_array($categories, MYSQL_ASSOC)) {
  if (isset($category) && $category == $row['catid']) {
    echo "    <option value=\\"".$row['catid']."\\" selected=\\"selected\\">".$row['title']."</option>\
";
  }
  else {
    echo "    <option value=\\"".$row['catid']."\\">".$row['title']."</option>\
";
  }
}
?>    
  </select>

On caching: I don´t understand the concept of this approach. I think it´s better to cache pages requested by users not pages changed by the coder.

Caching is something that should be done by proxy servers or browsers I think. If the delivered content only depends on GET paramters every HTTP cache will work just fine. The HTTP protocol offers means to control the behaviour of caches, e.g. with the “Expires:”, “Cache-Control:” or “Last-Modified:” headers. Squid (http://www.squid-cache.org/) is quite some times faster than every PHP script you could think up and it offers a special “http-accelerator” mode which is designed exactly for setups like this (see http://squid-docs.sourceforge.net/latest/html/c2416.html).
In order to let squid cache URLs with a “?” sign, one has to remove the line in the default configuration which forbids this.
It took me some hours to find out that I have to uncomment this line:

acl QUERY urlpath_regex cgi-bin \?

Sorry, I wanted to say “… <em>comment out</em> this line: …”

Hi, great article! I actually came up with something very similar myself, and have a suggestion to make.

Instead of:

$contents = ob_get_contents();
ob_end_clean();
return $contents;

I find it neater (and possibly faster?) to use:

return ob_get_clean();

I hope this helps.

Kind Regards,

Chris
chris SPOT wydra FUNKYASYMBOL gmail SPOT com