Pattern Help - Templater

Hi everyone,

So, I’m going back and forth with several ways I could implement this, but I can’t decide which.

Basically, I have an MVC setup. The Model and Controller are both PHP classes. However, I want to keep the View simple by making it more or less an HTML page (with tiny PHP bits). I want to make the Controller or a Model available to the View so they can get all the info it needs from them.

So, the obvious approach would be to just global the Controller or Model. However, I don’t like this approach because I don’t like random global values floating around. I like to have the one global class I need and that’s it.

The other would be to have a Singleton which keeps track of the Model and/or Controller my View needs, then let me call it this way: MySingleton::GetModel()->GetValue(). This approach is better, but I’m trying to avoid Singletons as much as possible.

My other approach, the one I’m closest to going with is to have a class that holds the Model and Controller and provides access to it’s methods by basically routing them through __callStatic. So, the last example would turn into something like: MyInterface::GetValue().

I like this approach the best, mainly because it shortest to type, but it also should work out pretty well. I’m just not sure how it may go with Unit Testing. I would only ever have one Controller or Model (most likely a Model where there is a 1:1 relationship between certain Models and a related View). That Model changes, so it would be an injectable dependency given to it in runtime, so I should be able to stub and mock it just fine.

Anyone see any major flaws with my last approach, or have a better idea?

Thanks.

So, I did come up with one serious con to my approach: since I’m passing everything through a magic method, my IDE auto-complete will be utterly useless.

Why not just assign the model to a scoped variable/property in the view?


<?php
class Controller{
	public function indexAction(){
		$this->view->bind('model', $this->model);
	}
}

Because I’m trying to keep the view simple, I wasn’t planning on making it an actual object… just an HTML file with bits of PHP (like Wordpress templates):


<?php
class Controller {
  protected $view = "view.php";

  public function render() {
    require_once($this->view);
  }
}

// view.php
<!DOCTYPE html>
<!-- more -->
<p>Hello, <?php echo $interface->GetName() ?></p>
</body>
</html>

I’m not strictly opposed to making the views classes, but I’m not sure the best way to put them together in a way that doesn’t end up an endless sea of “if() : ?> <p>Hi</p> <?php : endif” and HEREDOCs.

The idea is that it would be themeable by people that aren’t PHP experts. :wink:

Ah, I see.

In which case, I’d look to implement a templating library which would hide away the PHP stuff, or at least make it readable; Twig would be my recommendation. Even if it’s just for the added ability to gracefully render a buggered template, with feedback for the user, you’d be gaining a huge usability win.

So, keeping away from OOP, how about something like this then?


<?php
function render($template, array $arguments = array()){
    ob_start();
    extract($arguments);
    include $template;
    return ob_get_contents();
}




echo render('home.html', array('model' => $model));

I’ll have to give Twig a try. I want this to be really high performance, but it seems like Twig is probably light enough that it won’t have a substantial affect.

The function you mention could work. The only problem is I’m trying to keep away from global values. What I’m designing I want to be able to integrate with other systems (like WP, which is notorious for having lots of variables in the global namespace) and I want to avoid any potential conflicts. Also, if I extract them in a function, I’d still have to explicitly call global in the template, right?

Looking at Twig, it seems I can pass it variables to render against, which should let my template thing of them as global, but (hopefully) Twig keeps them properly contained. Looks like that (or basically reinventing Twig which would be silly) would be my best bets.

Thanks. =)

(Geez, I’m picking.)

You could pseudo namespace any resources you pass into the view.


<?php
$resources = new stdClass;
$resources->model = $model;
echo render('user.forgot.stuff.html', array('resources' => $resources));


$resources->model->getUsername();

Or summick.

That’s not a bad idea.

I’ve actually started using Twig and it seems to be working out pretty well without too much overhead. It looks like they already have automatic generation of a kind of “opcode” for Twig which works quite well.

Thanks.

“extract” extracts to the current symbol table. That means if you extract within a function, then the extracted variables are local to that function. No globals.

The “render” function Anthony posted is probably the simplest you’re going to get. And it’s a fairly clean solution too. (Though, Twig is probably still better.)

Either way, I’d advise against passing in the model directly. Ideally, the controller will pull from the model, then pass those values on to the view. The benefit is that the view won’t need to know or care where the values came from. The values might have come from a database, or they might have come from a form submission, or they might have come from a unit test. This way your views are more independent, more reusable, and more adaptable to change.

Hmmm, I knew what extract did, but I don’t think I realized if I required a file it had access to it’s requirer’s symbol table. Interesting.

I agree about keeping things flexible. What I ended up doing was having an abstracted “Templater” class which is responsible for loading the template file. The templater loads a specific template from a hierarchy based on certain attributes (similar to Wordpress). The controller feeds this information into the templater. While it does pass it a model, it isn’t a hard-coded model, so I can pass in just about anything (it just has to extend the base class “Model”), for unit testing and flexibility. =)