In this article we will introduce a powerful new tool in the arsenal of developers – the ViewModel. This provides MVC applications a natural location for presentation logic and lazy functionality while maintaining the segregation between the layers of responsibility within the code. It allows designers access to data and methods they need, while hiding aspects that aren’t needed at view level.

The tried-and-tested Model-View-Controller (MVC) pattern has become the mainstay of Web applications development, and numerous PHP frameworks such as Zend, Symfony and Kohana all implement variations on it (Ed: see also the post on Hierarchical MVC we featured recently).  Indeed, pretty much any modern Web framework has an understanding of the important segregation of duties inherent within MVC.

It is precisely this segregation that leads to a certain greyness around the all-important View, particularly on sites where multiple content items are displayed in different ways.

To illustrate this, consider the example of a subscription-based website with multiple articles per page.  Articles can be displayed either as the main article on the page, or as headlines or teasers linking to the main text.  For the purposes of this example, we will use Zend Framework, and assume articles are garnered from a Service API, and turned into Example_Content_Article Models in an action helper used by the Controller.  We’ll also assume that the helper takes care of any dependency injection requirements of an Article Model from the Bootstrap.

There are a number of ways you can inject information regarding Articles from the Controller into the View, and we will examine these in turn, starting with the simplest case.

Flattening Data

One approach is to take each Article Model, retrieve the title and URI of each article, assemble an array of these values, and then inject that into the View. The controller code would then look something like this:

However, there is a “gotcha” with this approach.  For a start, there are a lot of things in the Model we don’t want the design team to have access to, since they are dangerous functions and mistakes could happen. For example:

In the event that setHeadline() is a setter function, not only will this small typo not display a headline, if the Model acts as a gateway back to the Service layer, then this view code may have just wiped – permanently – the headline of all ten articles.  QA would probably find this; however unit tests would often look at the Controllers – i.e. the business logic back end – rather than testing the View.  Selenium tests would pick up that no headlines are showing, but would be unlikely to diagnose that ten articles have had their headlines wiped.

There are a number of other issues with injecting Models, assuming that typos are not your main concern.  To aid performance, we want to lazy-load the body, images, and even comments for articles as and when requested.  This frees the development team from having to write the exact logic and instead focus on tools to provide designers with.  But designers are generally not performance experts – their expertise is interface and creativity – so there is a risk of having inefficient code added using this system.

Then of course, there’s always the possibility that we enable the use of code like this from a view …

In organisations where front end development is done by a third party, this is a serious consideration.

Creating tools that are both useful and yet not overly powerful is a difficult line to walk, and causes either constraints on the Model or on the View, neither being particularly satisfactory. The Model becomes a bloated chimera, full of presentation logic as well as the core business functionality. Designers and front end developers have to wade through a mass of documentation on functionality they care little about just to work out how to get a headline out of an article, or find the author.

The third way…

Any developer that thinks that the View should have almost no logic in them is going to constrict the creativity of their designers, and thereby the site.  This is a simple fact of website design – an ambitious front end relies on the tools to deal with a variety of layouts based around factors in the data.  “Simple” aspects, such as switching to a different column layout if the number of articles exceeds a given number, need business-grade tools.  So, how do we give the designers the tools to be as creative as they like, while letting the developers concentrate on that new cool Services API we would be writing if we weren’t busy with presentation logic?

The Model-View-ViewModel pattern is attributed to being the creation of Microsoft as an evolution of the Presentation Model pattern created by Martin Fowler. Aimed at creating presentation logic for XAML-based applications, the logic applies neatly to PHP applications using MVC.

To illustrate the idea, here is an example of how this might work:

This code sample shows a ViewModel helper, so this would seem like an ideal time to introduce the concept of ViewModels. ViewModels are – in this instance – a combination of the Decorator and Adapter design patterns. They allow the development team to open up a variety of tools to the View without giving the designers access to functionality that was not intended for use in a view setting.

With this ViewModel, the designers have access to getHeadline() whenever they want, without having access to setHeadline(). We can then continue to map the ViewModel to getBody(), getImage(), and whatever else is needed, without fear of exposing functionality such as setter methods, inappropriately (remember, we are assuming in this example that the Article model has direct access to the Service layer, so that we can lazy load additional information as we need). Here is an extended example to allow our frontend team to load up images, but with restrictions.

To avoid having to write an exhaustive list of methods, we could event use the magic methods __get(), __set() and __call() to our advantage:

Putting additional presentation logic within the ViewModel now provides us some separation and allows us to add this here, without it feeling like a kludge:

With the ViewModel, we can also make View-specific decisions that may enhance performance. For example, we can set up a ViewModel with a cache object before injecting it into the View, allowing it to cache operations on the Model without resorting to something as brute force as page-level caching. Using the previously mentioned ViewModel helper, we wrap the Model an enclosing ViewModel:

If the article has markup, such as UBB, then the ViewModel can also parse the body copy before returning it to the View, or paginate it. All the while, the original Article Model is safely tucked up inside, feeding information to the ViewModel as needed.

To conclude, the ViewModel is an effective design pattern for any website with a requirement to provide detailed encapsulated presentation logic, while still keeping business objects free from needing any View-specific functionality within them. It promotes lazy-loading for performance and necessity, while still maintaining good practice such as dependency injection and segregation of responsibility. And, your design team will love you for it.