In the previous two parts of this series of blog posts, I’ve been looking at the task of implementing complex views with the Zend Framework. Part 1 looked at what complex views are, what support for complex views the Zend Framework offers out of the box, and a reference to two design patterns useful in adding further support: View Helper and Composite View. In Part 2, I tackled the View Helper design pattern.

As a brief recap, the View Helper pattern promotes the idea of creating helper classes which allow the View layer of a Model-View-Controller application to directly query the Model layer in a read only fashion – effectively bypassing the Controller layer altogether. In such a way, the pattern offers the option to programmers using the Zend Framework to avoid using the current method of nesting Controller Actions with the Zend_Controller_Action::_forward() method which can be an overly complex approach for parts of a View we know are common to many pages.

In this post, I offer a brief explanation of the Composite View pattern. It’s beyond its scope to show an implementation using the Zend Framework though that’s what I’m building up to accomplish in a later blog entry ;) .

If you haven’t already guessed, the Composite View pattern is related to the Composite Pattern as defined by the Group of Four (GoF). If you’re not familiar with the Composite Pattern, an excellent PHP article for it was published on Zend Devzone and is worth reading.

Here’s a UML diagram of the class relationship although we do things a little different below :) .

Composite View UML Class Diagram

In brief the related Composite View pattern organises View objects into a nested tree structure, in which both parents and children implement some common interface (let’s say render() for now). You can think of each View representing a single element of the overall page, with parents representing sections of the overall page which may contain other component elements. The essential characteristic, inherited from the Composite Pattern, is that the common render() method can be called from the root View, and this method call propagates across all nested objects in the tree until the output from all child Views is finally aggregated into the overall page we intend sending to the browser.

With this description we can make a few assumptions regarding the Zend Framework. The main one being we will need multiple instances of Zend_View to pull it off (as distinct from multiple Controllers). Also all this talk of objects hasn’t explained how the nesting is controlled. We’ll handle the second now, and come back to the Zend_View multiplicity after.

There are two methods of handling nesting of View objects. The first follows a purely object based scheme, where objects are nested and combined at runtime. The second passes control over nesting to our friends – the templates. The template method basically involves adding a function (think of the Composite Pattern’s interface for “composites”) to include another template. Here we’ll call it “attach”, though it could be anything you prefer. We’ll look at this approach below since it’s the simplest one to follow if you’re familiar with Zend_View templates. In addition, the template approach is probably the easiest for programmers and designers to handle since it allows the View layout to be put in place around all these composite View includes.

Now, we may appear to have come full circle here – this sounds suspiciously like a glorified “include” statement but there are differences. The main one being each composite “attach” creates a new View object which can be sourced from other Modules, and with Module specific helpers and filters (and of course Model accessing View Helpers!). If we assumed the composite method was “attach” (common Composite Pattern method), a composite template could look like:

articlelist.phtml (part of the imaginary Articles application Module):

[geshi lang=php]attach(‘stdheader.phtml’, ‘default’); ?>

attach(‘overbody.phtml’) ?>

articles as $article): ?>

title ?>
summary ?>

attach(‘underbody.phtml’) ?>

attach(‘stdfooter.phtml’, ‘default’) ?>[/geshi]
overbody.phtml:

[geshi lang=php]

attach(‘last5headlines.phtml’, ‘Blog’, array(‘feedUri’=>’http://www.planet-php.net/rss/’)) ?>

[/geshi]
Here we have two templates, both utilise an imaginary attach() method from the View object to attach new sub Views to the template at specific locations within the layout (you’re right in thinking attach() will handle rendering of the child View). It also allows for a template to attach Views from other Modules of the application if required (and would transparently manage the different View settings for that Module). I’ve assumed the lack of a “module” parameter means the attached View should come from the current Module only. The last overbody.phtml template allows for more dynamic parameters targeting the RSS View Helper utilised by the Blog Module’s last5headlines.phtml template where we’re using the View Helper pattern to grab headlines from the given RSS feed. We visited very similar functionality in my last post.

Of course in all this we haven’t ruled out Controller nesting completely. That too is still possible, even alongside View nesting and in a very similar fashion. Since each element attached is an independent entity you can mix and match what you want to use, even from other Modules. Of course with all this floating around we still haven’t seen usable code yet! Well, that one’s for another blog entry :) .

Back to the multiplicity issue for a moment, i.e. the presumed use of multiple Zend_View instances. You can guess that Zend_View will need to be subclassed and/or a standard helper class containing the attach() implementation added. There are other issues also. For example, each View object needs to be independently configured before use – i.e. for paths, encoding, etc. In Part 4 of this series I’ll take a stab at adding finer control over creating View objects in a simple reusable fashion.

I’m sure many of you will already suspect the design pattern that will involve ;) .

Related posts:

  1. Complex Views with the Zend Framework – Part 2: View Helper Pattern
  2. Complex Web Pages with the Zend Framework?
  3. YAML for the Zend Framework – well, maybe…
  4. OpenID library for the Zend Framework?
  5. Doing the Poka-Yoke