Well, I've implemented a composite view system. Still not using the Zend Framework, though - it's routing system makes my head hurt :cry:
What I realized with the format issue (at least with my stuff) is that the HTML format was the only format that could have multple possible templates being asked for. In a controller, you might ask for the two-column, html template or the three-column, html template. But all the other formats would really only have one template. JSON, iCAL, RSS - there really isn't alot of different layouts you would want to use for those.
Cacth me, if I'm missing anything there.
Although the View code in my project supports passing Model data to the Views (templates, and blocks) I've left that code out in these examples. Trying to keep it clear on the formatting problem.
Code: Select all
abstract class View
{
abstract public function render();
}
class Template extends View
{
private $filename;
public $outputFormat = 'html';
private $blocks = array();
public function __construct($filename="default",$outputFormat='html')
{
$this->filename = $filename;
$this->outputFormat = $outputFormat;
}
# Template files must include a call to $this->includeBlocks(),
# when they're ready for the main content
public function render()
{
include APPLICATION_HOME."/templates/{$this->filename}.inc";
}
# Callback function for template files
private function includeBlocks()
{
foreach($this->blocks as $block) { $block->render($this->outputFormat); }
}
}
class Block extends View
{
private $filename;
public function __construct($filename)
{
$this->filename = $filename
}
public function render($outputFormat='html')
{
include APPLICATION_HOME."/blocks/$outputFormat/{$this->filename}";
}
}
After updating the Views to handle different outputs, I still wasn't able to comletely remove Format checking from inside a controller. (Front Controller or Action Controller or whatever controller routing you've got.)
I was able to boil it down to just an Either-OR check. Either there was a format requested, or we're using the default template, which would be defined in the controller. In the example below, I leave the default file and format defined in the Template class. So my controller code now looks like:
Code: Select all
$userList = new UserList();
$userList->find();
$template = isset($_GET['format']) ? new Template($_GET['format'],$_GET['format']) : new Template();
$template->blocks[] = new Block('users/userList.inc',array('userList'=>$userList));
$template->render();
This works so far. However, I'm concerned about the need to pass the $outputFormat as a parameter to the block->render(). Waiting until render time to throw an Exception if there's no matching file *might* cause problems later on.