Tutorial 2: Pulling additional view information

Posted by Dave Redfern (Writer), Tutorials on 08 Jul 2008 @ 19:50

Getting Started

For this tutorial you will need to have used the main framework and have some familiarity with the MVC system. Completing Tutorial 1 should give a basic knowledge.

This tutorial will build on the files created from tutorial 1 so having a copy of them would be useful. If you have not looked at the first tutorial you should do so now.

Additionally you will also need:

And now on with the tutorial...

Requesting controller views

In MVC systems (indeed many web systems) certain actions are repeated time and time again with the same output, but different display needs. A prime example would be a set of headlines, or a random comment.

One solution is to manually code this on every controller and model and then work the data into the view. While part of this can be re-used (e.g. an object wrapper for searching for data), pushing the information into the view becomes messy and introduces a lot of "cut and paste" either in the controller or in the view files.

In some systems the part of the display can be encapsulated into a single separate template which is then injected into the view via the controller. e.g. a custom function that will pre-format a table or a list of news headlines. While this may be useful for a website it does not help if you then need the output in XML or WML or some other form.

Some MVC systems adopt this method where data is fetched and formatted and then injected directly into the view.

This is bad practise as once created, the data cannot usually be transformed again (unless it is XML and an XSLT applied to it making another set of transformations on the same data). While CSS can be used to do a lot of formatting it is not an ideal situation and you still have content that is designed for only a single output type.

In Scorpio injecting data into a view should never happen. In fact the controller should not do anything more than request a specific view. It is down to the view itself to request additional information from the system. Note that these are ONLY READ requests for information, and are not modifications to the data. That is why all save, delete and set methods are blocked by the output wrapper.

This additional data is requested by using the method getControllerView() from the current view template or if using the Smarty system, the custom function: {includeView}.

This tutorial will look at setting up the controller and view to allow this to be accomplished with the guestbook data, principally to be able to display the most recent 5 entries on the home page.

The guestbook controller

The first step in the process is to setup our guestbook controller on the customer facing site so that additional requests can be made to it for specific views. These requests will be rendered using whatever the request context is.

Custom views are added via the initialise() method. Locate this method and the existing getControllerActions(). We will set-up the views below this.

Additional views are held in the mvcControllerViews object that can be fetched using getControllerViews(). Similar to the mvcControllerActions, this has a "fluent" interface allowing the setting of views to be chained together.

We need to add:

//guestbookController.class.php
/*
 * Register permitted standalone views 
 */
$this->getControllerViews()->addView('top5');

This will register the view "top5" as an allowed view to be called by includeView or getControllerView(). A specific hardcoded name is not as useful as a class constant, so define a new constant near to the existing ACTION_ constants:

const VIEW_TOP5 = 'top5';

Update the previous code to reference the constant.

So we have a named view, how do we allow this to be pulled from the controller?

All view requests are passed to a method called fetchStandaloneView(). This accepts an array of parameters one of which must be named 'view'. This method will need to be created and configured for the guestbook controller:

/**
 * @see mvcControllerBase::fetchStandaloneView()
 */
function fetchStandaloneView($params) {
	switch ( $params['view'] ) {
		case self::VIEW_TOP5:
			$oView = new guestbookView($this);
			return $oView->getStandaloneTop5View();
		break;
	}
	return '';
}

Above we have added the method and defined that the view 'top5' will fetch a specific view from the guestbookView object. Note how a string is returned, even from the view: there is no direct display, the output is returned to the calling template.

And that's all the changes that need to be made to the controller. Next up are the model and view.

Model and view changes

The model

There are 2 ways of modifying the model to fetch the data that we need. The first is to leverage the existing listOfObjects method to support "paging" (as of 0.1-beta4 objects built using the default template will already include offset/limit support) and set this to return newest first; or: create a dedicated method to fetch just the top X etc.

How this is done and which to use is left as an exercise to the reader, this tutorial will use the listOfObjects method as built by the generator with a single modification to add ORDER BY createDate to the query.

With that done, the model changes are complete.

The view

Finally we come to the view. The changes to be made here have already been dictated by the controller in the controller changes. Remeber the method call through to the view we added? We now need to create this.

Open the guestbookView and add the following method:

// guestbookView.class.php
/**
 * Displays the top 5 most recent messages
 *
 * @return string
 */
function getStandaloneTop5View() {
	if ( !$this->isCached($this->getTpl('top5', 'guestbook')) ) {
		
	}
	return $this->compile($this->getTpl('top5', 'guestbook'));
}

This will compile and return our top 5 most recent entries from the guestbook. A template will need creating within the views/guestbook called top5.html.tpl.

Note how the site path is given to locate the template. This is very important, if it is not included, then the current request path is used which will not necessarily be to the guestbook.

Finally we add our model and a list of the top 5 entries:

$this->getEngine()->assign('oModel', utilityOutputWrapper::wrap($this->getController()->getModel()));
$this->getEngine()->assign('entries', utilityOutputWrapper::wrap(guestbook::listOfObjects(0, 5)));

Finally we need to create the template and arrange our layout. This could be a table, list or something more complicated. Again, this is left up to the reader to implement. For this tutorial (and for the sake of speed) this top5.html.tpl will simply feature:

{* top5.html.tpl*}
{$entries|printr}

Once done, the final step is to modify the home page to pull the data.

Fetching the guestbook data

The final step is fetching the data. In this tutorial we are using the default Smarty engine (as seen in the template file) so to fetch this data we will use the {includeView} custom function (for PHP the view getControllerView() method needs to be called).

This function (and the method) take the following parameters:

Additionally; if any other parameters are passed through they will be passed into the requested view (in PHP these must be specified as a string of parameters e.g. param1=value1¶m2=value2).

Open the home.html.tpl file and then within a new div (or however you want to handle it, and the following:

{includeView controller=guestbook path='/guestbook' view=top5}

Save the changes, and refresh your browser. You should now see the guestbook entries (if you had any to display!).

There are many other examples of this throughout the baseAdminSite. Any number of additional views can be created. Simply update the controller and views and add any additional model logic to handle what you wish to do. Remember that the controller, path and view are always required when including a controller view to help route the request. Additionally, avoid placing any rendering into the model or controller. This will help keep your system clean and ensure that the view context is preserved.

Download the basic files as a Zip file.

< Return to article