views:

183

answers:

5

I try to develop my own little framework. For this, I'd like to read up some templating techniques. I know that templating is a really complex topic, but knowing some strategies could help find the right one.

Please, if you mention one, don't just write "smarty" for example. Write a little about the concept behind it.

Let me start with an idea: To make things simple, my template files are just PHP files that contain HTML. Templates may include other templates. The data is inserted into the templates through a $data variable, which is an associative array containing all the data for the template.

So, at the first stage a controller performs some action and builds up that $data array. Next, the appropriate template will be included.

Problems: A Template might have to include not only templates, but also controllers. i.e. displaying a breadcrumb or menu (with fairly complex logic behind, far too complex to be handled in a template).

A: 

This is exactly how I do it, instead of calling a Controller in the View (WHAT?!?) I just compute all the necessary data for the view in the Controller that calls the View in the first place.

A View should never call a Controller / Model! BUT, if you must you can do something like this:

function Controller($pathToControler) // instantiates and returns the Controller
function Model($pathToModel) // instantiates and returns the Model

That way, inside your view you can do something like this:

$this->Controller('path/to/blog/tags.php')->List();

Again, you shouldn't use this pattern, I'm just giving you solutions, not encouraging them.

Similarly, you can also call another view from within a view, like this:

$this->View('path/to/views/header.php', array('title' => 'Hello World!'));
Alix Axel
There is no reason, why the View shouldn't be allowed to call upon the Model, as long as it does not alter the model's state. On the same grounds you may call the Controller from the View, for instance, to aggregate output from multiple controller actions, thus fostering reuse of code.
Gordon
@Gordon: Yeah, sure. But that isn't the way the MVC pattern is supposed to run.
Alix Axel
Well, it's a bit odd to claim MVC was never *supposed to run* that way, when it was never conceived with the web in mind at all. The pattern dates back to 1979. If anything, then the *supposed way* is definitely not how everyone uses MVC today. The whole trip over HTTP from Browser to FrontController to Controller to Model and back to the Controller that creates and sets an entire new View (instead of the Model notifying the View about changes in it and the View updating itself) is not part of the original MVC concept.
Gordon
I don't understand the down vote but here is what **I** think: the View as the name suggests is supposed to render the output from the Model, and the Controller is supposed to get the input and work with it on the Model. You're basically saying that is okay for the View to do the Controller job and it's also okay for the View to call the Model directly; so I ask, why **MVC**? **MV** also seems to do the job, hell lets drop everything and just stick with **V**.
Alix Axel
No. I did not say, put request handling into V, neither did I say put M logic into V. I said it is okay to *call upon* M and C from V, if that is required to render M. And that's the whole point. Doing so will not violate separation of concerns, nor will it create additional dependencies.
Gordon
http://stackoverflow.com/questions/1973221/can-i-call-a-model-from-a-view
Alix Axel
+2  A: 

I really enjoyed zend-framework approach to this, and have used it myself in our framework. You will have a view class with will have things like:

$view = new View();
$view->setTemplatesPath('.....');
$view->assign('name','value');
$view->render('index');

the render method will take all the variables stored and make them properties and include the template based on the Path set, so in your templates you will have:

<?php echo $this->foo; ?>
....
<?php echo $this->load('header'); // this includes another template ?>
solomongaby
He's already doing that in a similar fashion, what he wants has nothing to do with this.
Alix Axel
+3  A: 

Have a look at the section Web Presentation Patterns, especially Template View, Transform View, Two-Step View. For stuff like rendering breadcrumbs or pagination, you can utilize a View Helper pattern.

Gordon
A: 

My strategy is as follows:

  1. Try and use the minimum of PHP in the template and if possible down to none.
  2. I have created classes for various components commonly found in web pages, one of them is tpanel which I am using to demonstrate the concept below
  3. tpanel for example would handle all the logic to create a menu, parses a small template for 'navigation_menu' and sends the result for final inclusion to overall template.

Effectively I am creating 'blocks', very similar to what Drupal does - if you are familiar with it.

        $this->load->library('tpanel');
        $s=$this->tpanel->get('date',$data);
        $s.=$this->tpanel->get('navigation_menu',$data);
        $s.=$this->tpanel->get('ajax_menu',$data);
        $s.=$this->tpanel->get('spacer',$data);
        $data['title']='List of Databases';
        $post=$this->uri->segment(5);
        $blog=(file_get_contents('../'.$dir.'/'.$post.'.dat'));
        $s.=markdown($blog);
        $data['content']=$s;
        $view='/admin/admin_simple_view';

The system is much more flexible that what I have shown above. For example the tpanel->get('ajax_menu, $data) also handles the script settings using jQuery.

I have been also looking at Django lately and they have some very good ideas on templating. It might be worth getting a look, even if you are not a Python programmer, especially how they handle inheritance.

yannis
A: 

This is not directly related to your question, but have you considered client side templating? John Resig has a nice micro-template in Javascript that will work with web services and other Ajax techniques. It's quite simple to do a get or post for the template, and then do another get/post for your data. It's quite handy.

David Robbins