Skip to content
Luke Morton edited this page Oct 23, 2011 · 4 revisions

Basic Usage

Beautiful_View aims to be a drop in replacement for Kohana_View. Once you have included this module in your application it will overwrite the [View] class. Do not fret though since it should be completely compatible with the Kohana_View API.

[!!] The only backwards compatibility that is intentionally avoided is [Kohana_View::global_bind()]. I have not implemented this at all and do not intend to.

Here I will explain the basic usage of Beautiful View. You can checkout the reasons why elsewhere.

So anyway here is some code that looks exactly like the standard Kohana view.

<?php
$view = new View('post', array('title' => 'An example'));
$view->set('content', 'A paragraph.');
$view->author = 'Luke Morton';
$css = array();
$view->bind('css', $css);
$css[] = '/css/reset.css';
echo $view;

As you can see most of the API is exampled above. It mimics Kohana_View precisely. Behind the scenes it does some pretty interesting stuff but that will be explained another time perhaps.

Introducing the ViewModel

In the old style you simply handle data in an array. Beautiful View handles data within ViewModel objects. The purpose of a ViewModel is to prepare data from a Model for a particular view. A ViewModel prepares data for use in a template, but it does not have any notion of the template or medium the template renders to.

<?php
class View_Post extends ViewModel {

	protected $_post;

	public function __construct(Model $post)
	{
		$this->_post = $post;
	}

	protected function post()
	{
		return $this->_post;
	}

	public function title()
	{
		return $this->post()->title;

	public function content()
	{
		return Security::xss_clean($this->post()->content);
	}

	public function author()
	{
		return $this->post()->author;
	}

}

Preparing your data in a ViewModel allows you to only expose the data you want from a Model. You can also run operations on your data such as [Security::xss_clean()].

[ViewModel] does not describe a ::__construct() method and therefore you are free to define one or not. The only two methods it does define are ::set() and ::bind().

[ViewModel] has no rendering capability. It only describes data. It can then be passed to [View] instead of an array to be rendered.

<?php
$viewmodel = new View_Post(new Model_Post(1));
echo new View('post', $viewmodel);

You can still set data to your [ViewModel] via [View] using all the standard methods.

Using Templates

Not only does Beautiful View introduce [ViewModel] it also provides the [Template] class. This abstract class is extended to create various Templating engines for Beautiful View. This module comes with three:

  • [Template_PHP]
  • [Template_Mustache]
  • [Template_JSON]

Template_PHP

The default templating for Beautiful View, it runs in the same vein as Kohana_View's template rendering.

If you pass [Beautiful_View] an array of data then this will be placed into a vanilla [ViewModel]. You may also use a vanilla [ViewModel] directly. Either way when rendering a the view data using Template_PHP the [ViewModel]'s properties will be exposed as variables like Kohana_View.

Using any other object that extends [ViewModel] the only variable exposed to the view is the [ViewModel] inside the $view variable.

What follows is an example that hopefully spells out the difference between passing in a class that extends [ViewModel] and passing in an array.

example/viewmodel.php

<h1><?= $view->title() ?></h1>

example/array.php

<h1><?= $title ?></h1>
<?php
class View_Example extends ViewModel {

	public function title()
	{
		return 'View_Example Title';
	}

}

echo new View(
		new Template_PHP('example/viewmodel'),
		new View_Example);
	
echo new View(
		new Template_PHP('example/array'),
		array('title' => 'Array Title'));

So you see, the templates do differ! This is your warning. The reason for this is to maintain backwards compatability with the old View API whilst your new templates can benefit from accessing the object with $view.

As with [Kohana_View] your PHP templates need to be placed in the views folder. You can extend [Template_PHP] yourself and overwrite the ::$_dir property to change this to the more sensible templates folder.

Template_Mustache

For rendering your mustaches of course :{) It works in a similar way to that of zombor's Kostache. In fact if you understand how Mustache.php works you will find that [Template_Mustache] is a very simple wrapper.

Mustache templates should be placed in the templates directory.

Differences with Kostache

It's easier for those of you who use Kostache to just let you know the differences:

  • You cannot set partials on the ViewModel.
  • The template path is set when you initialise [Template_Mustache] and does not reference the name of your pViewModel].
  • You cannot set the template path from your ViewModel.
  • There is no equivelent to Kostache_Layout currently.

So why differentiate? Beautiful_View is about the complete separation of a template from a ViewModel. They should not really have any idea about each other. This means that either piece can be interchanged, this flexibility is awesome especially when flipping between [Template_PHP] and [Template_JSON].

Partials have to be set directly to the template using [Template_Mustache::partial()]. This is because partials are specific to a template not a [ViewModel].

I believe this separation is key although I think that I will need to come up to some [Kostache_Layout] equivelent. Perhaps something like:

<?php
$template = new Template_Mustache(
	'post',
	array('layout' => 'shared/layout'));
echo new View($template, new View_Post);

Whereby the second param of [Template_Mustache] can be an array of options. This way partials could be set via the constructor too. Let me know what you think.

Template_JSON

As modern web application developers we tend to use a lot of JSON as a means for communicating via XHR. I really want an easy way to either render a normal HTTP request using Mustache or if the request is XHR then to send the only the ViewModel data as JSON.

Now I could just call all public methods and place these into a JSON object but that doesn't give you the control that you might need to call only a certain amount of data.

This flexibility could be provided by some kind of JSON template file. To this end I have come up with a simple solution. You do actually write JSON templates. The top level properties of the JSON object are used to look up your [ViewModel]'s public methods and properties. The values are used as defaults if the public method or property does not exist.

Here is a JSON template as I imagine it:

{
	"title" : "Unknown Title",
	"navigation" : [],
	"content" : ""
}

There you have it! Then your [ViewModel] would be used to populate these values if set. I think it could be awesome!

Clone this wiki locally