It’s been a long, and hopefully interesting, road to Part 7. In this concluding entry to the long running, and oft delayed, “Complex Views with the Zend Framework” series I introduce the Zend_View Enhanced Proposal for the Zend Framework, elaborate on its operation, and provide some opinions on the ongoing debate over its implementation. So sit back, relax, here’s another long (be patient ;) ) blog entry.

Back in Part 6, I set some terminology for the concepts we had discussed in previous posts. Partials, Layouts, Controllers and Placeholders. These four concepts capture the main points of functionality Zend_View currently lacks, being a strict implementation of the Template View design pattern. The purpose of implementing these four concepts is to empower a Zend_View user with a sufficiently expanded template syntax so that they may both flexibly, and efficiently, create complex pages with reusable elements and with minimal effort.

You first port of call should be the Zend_View Enhanced Zend Framework Proposal. Please note that the referenced sample code is seeing an update this week – so don’t expect it to work perfectly right now. It appears that sample code is no substitute for a robust implementation even for a proposal so expect the code to be spruced up soon.

The proposal, since its launch, has seen a lot of debate and no small amount of competition. So your second port of call should be the under construction Zend_Layout Zend Framework Proposal. Zend_Layout is under the charge of Ralph Schindler and addresses, primarily, Layout construction. It’s narrower focus is expected to expand and directly compete against Zend_View Enhanced in other areas. I guess DRY and collaboration took the day off recently ;) .

Back to Zend_View Enhanced! The proposal, running on the back of the “Complex Views with the Zend Framework” series has approached the entire concept of View construction from the perspective of a user who wishes to utilise a template syntax.

This is an important distinction, since Zend_Layout has no expanded template syntax and is focused only on building a Layout based on aggregating the output of multiple Controllers (it does nothing to alter the Zend_View status quo I usually bemoan). The approach is pretty much identical in effect to using Partials – whereas Ralph has implemented a non-strict interpretation of the Two-Step View, I have implemented the Composite View which allows for using View Helpers, both of which compose output by building a tree of aggregated View output.

Zend_View Enhanced is however much broader than Layouts alone. It’s existence serves to “enhance” Zend_View – a strict template-based approach which is common across frameworks both in PHP and other languages. This has been accomplished using an existing Zend_View ability – view helpers. The proposal has no particular limit on view helpers, since in the Zend Framework, a helper is completely decoupled from the Zend_View class. In fact, only Layouts require minor alterations to the Zend_View_Abstract class – all other parts of the Zend_View Enhanced proposal rely completely on View Helpers.

I have proposed a number of helpers but the three main ones are:

• Zend_View_Helper_Partial
• Zend_View_Helper_Placeholder
• Zend_View_Helper_Controller

In addition, based on previous feedback and concerns noted by a few folk, including Maurice Fonk, Mark Maynereid, Ralph Schindler, and Jack Sleight, I have added specialisations of Zend_View_Helper_Placeholder. These offer specific interfaces for Layout elements which are overwhelmingly common and can benefit from being made obvious:

• Zend_View_Helper_HeadTitle
• Zend_View_Helper_HeadScript
• Zend_View_Helper_HeadMeta
• Zend_View_Helper_HeadLink
• Zend_View_Helper_Doctype
• Zend_View_Helper_HeadStyle

These are all extremely simple classes which leverage off the basic functionality of Placeholders, i.e. the ability for templates to define values which subsequently rendered templates (Layouts are always rendered last) can then reference. A simple example is a Layout which captures the output from a Login template. The login template can carry a snippet of code to set the HTML page title in the Layout using:

[geshi lang=php]headTitle(‘User Login’) ?>[/geshi]
I’ll discuss the specialised helpers later in the Placeholder segment. Subsequent entries may look at further enhancements on similarly small scales. For now let’s start with a meatier subject – Partials (aka Composite View).

Partial

When I originally posted Part 6 of this series, I defined the term “Partial”. It took less than a day to get inundated with comments/emails/IRC messages about “robbing Symfony”. I was overjoyed – Symfony’s View implementation captures the average user’s needs with a simple effective implementation. Indeed that’s why I referenced it in the proposal. Nevertheless, this is rather a short sighted accusation. Partials are extremely common in frameworks. Solar has them. Ruby has them. Need more examples?

The Partial has a dual role in Zend_View Enhanced: to render sub-templates in their own variable scope, and to implement the Composite View design pattern. Both rely on using multiple Zend_View objects, an approach which ensures variables do not conflict, and that intra-Module includes are allowable.

The Partial is a totally obvious enhancement. By enabling a User to use Partials it encourages the reuse of template snippets, and larger template View elements, with a simple inclusion mechanism.

[geshi lang=php]partial(‘userprofile.phtml’, array(‘user’=>$this->user)) ?>[/geshi]
Like I noted before, a Partial at first looks suspiciously like a simple include/render(). The difference is that a Partial occupies an independent variable scope (no name conflicts, accepts parameters) and can cross the Module barrier. In a Modular application, cross Module support can be very useful to integrate sections of a Module into your templates (e.g. integrating a list of blog article titles from the “Blog” Module into another Modules template).

Layout

Layouts were not a huge concern in this blog series. The thing with Layouts is that they are so simple to implement. A Layout basically decorates the resulting output from a View with common elements. The most basic Layout would add common header and footer sections to page output for example – such a simple thing to ask for. Since a Layout is treated the same way as a template, they can themselves make full use of Partials, Placeholders, Controllers etc. This makes them an effective means of enforcing a common Layout not simply on the end resulting page, but also on other sub-templates (a benefit of Layouts being bound to the View). Thus the Composite View implementation of Partials can nest Layouts for each distinct element.

[geshi lang=php]

headTitle() ?>


getLayoutContent() ?>
Copyright © 2007 Acme Layout Ltd.


[/geshi]

Constrast to Zend_Layout proposal

Ralph Schindler’s Zend_Layout proposal takes a different tack. It drives Layouts by composing the output of multiple Controllers. The key difference here is that it does not offer a template based solution – you must define a Layout in terms of Controllers, and requests to those controllers, outside of templates and Zend_View. There’s been a recent combative push to get Zend_Layout adopted – I think it’s adoption is inevitable given the Controller heavy focus the Framework weighs heavily towards. However there is no reason why a template based Layout approach should not equally be adopted – it’s simple, effective, and plays nice for anyone who prefers View Helpers when accessing Models.

I keep stating that both strategies do not conflict but I get the feeling the idea of a dual-implementation (Zend_View Layouts require about 30~ lines of code to be added to Zend_View_Abstract) has gotten lost in the noise of rattling sabres and previous FUD on the mailing list. The most annoying aspect of deep set competitiveness is that it stiffles collaboration, sets up a rival mindset and which can go to extremes in challenging simple ideas.

To those in the Zend_Layout camp not yet convinced, Zend_View Enhanced has absolutely no conflict with Zend_Layout. Implementing one does not invalidate the other, nor does it require a seismic shift in how Zend_View operates. It’s getting rather tiring having to explain that…

But, something more interesting than my proposal woes!

Placeholders

The idea of Placeholders is to allow templates to communicate data to other templates. For example, in my Layout example a login template communicated a page title to the Layout using the specialised Zend_View_Helper_HeadTitle helper. This helper, and the other Head* helpers are all basic classes which use the base Zend_View_Helper_Placeholder class to store this data under a predefined namespace (e.g. ZEND_VIEW_HTMLTITLE).

Placeholders are not the sole preserve of the HTML <head> element, but since Placeholders are most obviously useful to Layouts, and Layouts will almost certainly have a <head> element to fill, they are the most common use case. Of course, a Placeholder can be utilised almost anywhere to communicate data between any two templates. They can store data of any type from Strings to Objects. There is only one limiting factor – only templates rendered AFTER the current template can access stored values.

Let’s take an example which doesn’t concern the <head> element alone.

./scripts/article.phtml:
[geshi lang=php]headTitle($this->article['name']) ?>
placeholder()->set(‘layout_license’, ‘GNU Free Documentation License’); ?>

article->text ?>

[/geshi]
./layouts/layout.phtml:
[geshi lang=php]doctype(‘XHTML 1.0 Transitional’) ?>


headTitle() ?>


getLayoutContent() ?>
Copyright © 2007 Acme Layout Ltd.

placeholder()->has(‘layout_license’)): ?>
placeholder()->get(‘layout_license’) ?>


[/geshi]

So we’re starting to see a few benefits. Basic and specialised Placeholders are proving quite helpful in making Layouts common to all pages, and with enough flexibility to be easily adapted by the primary templates we’re rendering. As a plus, the specialised Placeholder helpers remove some of the cruft from the usual Placeholder API for common use cases.

Controllers

This was always going to be a questionable addition, however the feedback was sufficient to make me overlook my Controller-reduction attitude. Controllers aim to enable View aggregate output from a Controller. It seems, at first, that this is not completely advisable. What if a user (who is clinically insane ;) ) decides to start altering the Model from the View? In an MVC implementation where Views should only ever read (never write!) from Models this can only be a bad thing.

However, despite the risks of misuse, they can be a powerful part of the View puzzle. The capability to call Controllers from a View allows for one key effect: reuse. If you have an application with ready made Controller dedicated to rendering a complex page, is it better to push all that work into refactored View Helpers, Partials and Layouts – or simple reuse the existing Controller by aggregating it’s rendered output directly into a View?

It’s arguable. But my opinion is that not all applications, or Modules, will take the View Helper route. So in a bout of practicality I decided the ability should be proposed. If it saves time on integrating applications by enabling the reuse of existing controllers than I believe it’s worth it. Besides – it’s not like other Frameworks have a similar mechanism in place ;) . So let’s go befuddle our View with Controller dispatching…

./scripts/external/blog.phtml
[geshi lang=php]
headTitle(‘Planet-Acme Blog Entries’) ?>

Blog content aggregated from Planet-Acme Module


controller(‘index’, ‘index’, ‘Blog’) ?>

[/geshi]
./layouts/layout.phtml
[geshi lang=php]doctype(‘XHTML 1.0 Transitional’) ?>


headTitle() ?>

getLayoutContent() ?>


[/geshi]
Problems? The implementation’s effectiveness is of course directly related to the nature of the Controller’s output. If it’s unsuitable for direct embedding there is not much the View can do to resolve this without further tinkering.

Conclusion

The Zend_View Enhancement proposal is the culmination of the “Complex Views with the Zend Framework” blog series. From our early examination of the View Helper and Composite View patterns, to Part 6′s terminology setting exercise, we’ve gradually set in place the core requirements the proposal seeks to meet.

Folk have made it clear since I started writing this blog series, that Zend_View alone just wasn’t cutting it. The torrent of “layout”, “common view”, “complex views” questions to the mailing list has pushed the whole topic to the point of being a priority for the Zend Framework 1.1.0. It’s uncertain whether Zend_View Enhanced will ever be adopted in full – it seems more likely that bits and pieces will be integrated, or re-proposed in differing forms and implementations until Matthew (the Zender who leads the MVC bunch) brings all these ideas into a comprehensive approach.

If you haven’t commented on the Zend_View Enhanced Proposal please take the opportunity to do so. The more feedback, use cases, and edge cases that I get the more likely it is the proposal (and myself) can push your ideas to the Zend Framework team. If you are unable to comment (not a registered Zf developer Wiki user) please comment here, or post your thoughts to the Zend Framework General mailing list.