Patterns for Flexible View Handling, Part 1 – Working with Composites

This entry is part 1 of 2 in the series Flexible View Manipulation

Flexible View Manipulation

I would dare say that views, in the many forms they can take, are underrated entities in search of a true identity. From the first moment MVC started making inroads in the PHP community, the acronym’s “V” has been unfairly reduced to the level of a plain template whose responsibility is limited to rendering a few HTML pages.

While no one will disagree that the role of views is intimately bound to outputting data, treating them as just mere templates with little or no logic behind them is rather daft. Views not only can be full-fledged objects carrying state, but also observers of a model, flexible enough to accommodate and react accordingly to fluctuations whenever the model’s state changes. And while those changes surely will ripple down the fancy user interface, this is merely a consequence of their responsive nature rather than the primary reason for their existence.

On the flip side, this kind of late revindication raises an interesting point as well. If views are such nifty components, exposing to the outside world all sort of rich and wonderful features, we might believe that setting up a mechanism capable of massaging them in a pragmatic manner would be harder to implement than just rendering a few naive HTML templates.

In a sense, it could be. As usual, seemingly-complex issues can be addressed by appealing to simpler approaches. Moreover, since in many cases views are conceptually modeled as skeletal PHP objects sharing some sort of common rendering interface (thus honoring Polymorphism), it’s relatively simple to treat them either individually or in conjunction through the reins of a unified API.

If you reread the previous sentence, you’ll see a resemblance to the functionality that the Composite pattern brings to the table. That’s pretty nice, sure. Though, it’d be even nicer to inject recursively views into other views without spoiling the contract with client code, something that would let us implement some neat decorators further down the road capable of assembling pipelines of views at runtime which could then be rendered all in one go.

Sounds pretty much like nerd baiting? Well, it’s not. To overcome your skepticism, in this two-part tutorial I’ll show you how to implement from scratch a couple of customizable view handling modules by sinking our teeth into the goodies of the Composite and Decorator patterns.

Making the First Move – Implementing a basic View Module

Included in the classic GoF’s repertoire, the Composite pattern is one of the most glaring examples of the old “Favor Composition over Inheritance” mantra in action. Simply put, the pattern’s forces allow you to manipulate single and multiple instances of a given component by using the same API. This ability is especially appealing for traversing tree structures composed of leaf and branch objects (yep, objects fed with other objects) without having to clutter your code with conditionals, hence deploying an elegant solution that rests on the pillars of Polymorphism.

While in theory everything looks sweet and charming when it comes to consuming Composites, it’s rather complex to figure out how to put them to work in the real world to build up a flexible view module from scratch. There’s no need to feel anguish, as the implementation of the module in question is actually a fairly straightforward process, reduced to first creating a class capable of modeling the data and behavior of single views (the so-called leaf objects), and second defining an appropriate counterpart, responsible for manipulating recursively composite views.

Since in this case I want to keep the whole implementation concise and easy to understand from front to back, the first element I plan to add to the module will be a class charged with engendering individual views. Here’s how this one looks:

<?php
namespace LibraryView;

interface ViewInterface
{
    public function setTemplate($template);
    public function getTemplate();
    public function __set($field, $value);
    public function __get($field);
    public function __isset($field);
    public function __unset($field);
    public function render();
}
<?php
namespace LibraryView;

class View implements ViewInterface 
{
    const DEFAULT_TEMPLATE = "default.php";
    
    protected $template = self::DEFAULT_TEMPLATE;
    protected $fields = array();
    
    public function __construct($template = null, array $fields = array()) {
        if ($template !== null) {
            $this->setTemplate($template);
        }
        if (!empty($fields)) {
            foreach ($fields as $name => $value) {
                $this->$name = $value;
            }
        } 
    }
    
    public function setTemplate($template) {
        $template = $template . ".php";
        if (!is_file($template) || !is_readable($template)) {
            throw new InvalidArgumentException(
                "The template '$template' is invalid.");   
        }
        $this->template = $template;
        return $this;
    }
      
    public function getTemplate() {
        return $this->template;
    }
    
    public function __set($name, $value) {
        $this->fields[$name] = $value;
        return $this;
    }
    
    public function __get($name) {
        if (!isset($this->fields[$name])) {
            throw new InvalidArgumentException(
                "Unable to get the field '$field'.");
        }
        $field = $this->fields[$name];
        return $field instanceof Closure ? $field($this) : $field;
    }
    
    public function __isset($name) {
        return isset($this->fields[$name]);
    }
    
    public function __unset($name) {
        if (!isset($this->fields[$name])) {
            throw new InvalidArgumentException(
                "Unable to unset the field '$field'.");
        }
        unset($this->fields[$name]);
        return $this;
    }
    
    public function render() {
        extract($this->fields);
        ob_start();
        include $this->template;
        return ob_get_clean();
    }
}

As denoted before, views are appealing candidates who pray hard for being modeled as POPOs, and certainly this View class honors this concept. Its functionality boils down to just using some PHP magic behind the scenes in order to assign and strip fields out of the view which are in turn parsed by its render() method.

Considering the malleable nature of the class, it’s easy to get it up and running without much fuss. To do so, first we should make sure to define its default template, which at a very basic level might look like this:

<!doctype html>
<head>
  <meta charset="utf-8">
  <title>The Default Template</title>
</head>
 <body>
  <header>
    <h1>You are viewing the default page!</h1>
<?php echo $this->header;?>
  </header>
  <section>
<?php echo $this->body;?>
  </section>
  <footer>
<?php echo $this->footer;?>
  </footer>
 </body>
</html>

With this template in place, it’s time to see how to hook it up to the View class so that it can be populated and dumped to the browser. The following snippet does just that:

<?php
use LibraryLoaderAutoloader,
    LibraryViewView;
    
require_once __DIR__ . "/Library/Loader/Autoloader.php";
$autoloader = new Autoloader;
$autoloader->register();

$view = new View();
$view->header = "This is my fancy header section";
$view->body = "This is my fancy body section";
$view->footer = "This is my fancy footer section";
echo $view->render();

Not bad at all, right? And even though I have to admit the view implements a little more magic than what I’m usually comfortable with, it performs fairly decent when it comes to creating renderable view objects. What’s more, considering that the class is capable of parsing closures dropped into the template, we could be a little bolder and use it for generating two-step views. To accomplish this, we should create at least one minimalist partial file, called partial.php or something like that, similar to this one:

<p><?php echo $this->content;?></p>

Swapping out each template property with the partial would then be a trivial process, reduced to defining a few closures:

<?php
$view = new View();

$view->header = function () {
    $header = new View("partial");
    $header->content = "This is my fancy header section";
    return $header->render();
};

$view->body = function () {
    $body = new View("partial");
    $body->content = "This is my fancy body section";
    return $body->render();
};

$view->footer = function () {
    $footer = new View("partial");
    $footer->content = "This is my fancy footer section";
    return $footer->render();
};

echo $view->render();

We’ve managed to implement a pretty flexible view module which can be used for rendering isolated objects and even dummy partials. Regardless of all these virtues, however, the module still falls short when it comes to rendering trees of views. This could be done by nesting closures, which at least to my taste, would be a pretty sloppy solution. How about appealing to the Composite pattern instead? After all, it provides this functionality right out of the box, while retaining the essence of OOP.

Building a Composite View – Leaves and Branches as Equals

In fact, it’s pretty simple to amend the structure of the previous module to give it the ability to handle composite views through a unified API. The first change we should introduce is to make the View class an implementer of a few segregated interfaces rather than the single one it currently consumes. The set of contracts defined by these finer-grained interfaces would look as following:

<?php
namespace LibraryView;

interface TemplateInterface
{
    public function setTemplate($template);
    public function getTemplate();
}
<?php
namespace LibraryView;

interface ContainerInterface
{
    public function __set($field, $value);
    public function __get($field);
    public function __isset($field);
    public function __unset($field);
}
<?php
namespace LibraryView;

interface ViewInterface
{
    public function render();
}

Though not explicit, the most engaging facet of defining several granular contracts is that now the render() method can be equally implemented at the same time by a class handling standalone views and by others manipulating composite ones. With this feature, we should now refactor the signature of the View class so it can adhere to these changes:

<?php
class View implements TemplateInterface, ContainerInterface, ViewInterface 
{
    // the same implementation goes here
}

View is still a fully-renderable entity, even tough its functionality responds to the contracts imposed by disparate interfaces. At this point you might be wondering where and how the nuts and bolts of the Composite pattern might fit into this schema. Leave your anxiety behind and look at the following class, which… yep, has the neat ability for parsing recursively multiple views in one go:

<?php
namespace LibraryView;

class CompositeView implements ViewInterface
{
    protected $views = array();
    
    public function attachView(ViewInterface $view) {
        if (!in_array($view, $this->views, true)) {
            $this->views[] = $view;
        }
        return $this;
    }
    
    public function detachView(ViewInterface $view) {
        $this->views = array_filter($this->views, function ($value) use ($view) {
            return $value !== $view;
        });
        return $this;
    }
    
    public function render() {
        $output = "";
        foreach ($this->views as $view) {
            $output .= $view->render();
        }
        return $output;
    }
}

The CompositeView class is nothing but a plain view container disguised behind a fancy name, though its attachView()/detachView() tandem allows us to add and remove views at will, including other composite views. This nifty recursive ability, often present in typical implementations of the Composite pattern, brings a lot of flexibility for free. For instance, consider a common scenario where an HTML page is made up of the classic header, body, and footer. To make the example even easier, let’s say the sections have the following header.php, body.php, and footer.php templates tied up to them:

<!doctype html>
<head>
  <meta charset="utf-8">
  <title>A Sample Template</title>
</head>
<body>
  <header>
    <h1>Welcome to this page, which you're accessing from <?php echo $this->ip;?></h1>
    <p><?php echo $this->content;?></p>
  </header>
<section>
  <p><?php echo $this->content;?></p>
</section>
  <footer>
   <p><?php echo $this->content;?></p>
  </footer>
 </body>
</html>

In a traditional approach, each section could be easily assembled as an insulated view and rendered linearly, which is all fine and well. Nevertheless, we could use the CompositeView class and just render the whole page via a single method call, as following:

<?php
use LibraryLoaderAutoloader,
    LibraryViewView,
    LibraryViewCompositeView;
    
require_once __DIR__ . "/Library/Loader/Autoloader.php";
$autoloader = new Autoloader;
$autoloader->register();

$header = new View("header");
$header->content = "This is my fancy header section";
$header->ip = function () {
    return $_SERVER["REMOTE_ADDR"];
};

$body = new View("body");
$body->content = "This is my fancy body section";

$footer = new View("footer");
$footer->content = "This is my fancy footer section";

$compositeView = new CompositeView;

echo $compositeView->attachView($header)
                   ->attachView($body)
                   ->attachView($footer)
                   ->render();

The charm of this approach rests on the intrinsic flexibility the Composite pattern hides behind its hood. Considering that both plain and composite views are implementers of the same interface, it’s simple to inject them recursively and create complex layouts without having to amend a single chunk of client code.

The above example is in general pretty conservative since the recursive injection of composites actually never takes place. However, putting a more liberal plan into action, where single and composite views are just passed around onto other views, should be an easy process. If you’re feeling bold and want to give the view module a different twist, you have green light to do so.

Closing Remarks

Commonly placed under a shallow and fuzzy “flexible programming” category, the Composite pattern is pretty much a paradoxical example where the feelings of joy generated by its elegance quickly get swept under the carpet of a tangled implementation. When properly tamed, though, it proves to be a pretty a solid solution that allows us to manipulate easily view objects, either as isolated entities or in the form of recursive sets.

This doesn’t mean that one has to hold on tight to the pattern’s virtues whenever it’s necessary to deploy somewhere a view handling mechanism, as being that dogmatic is pretty pointless. What’s more, if Composites just don’t fit your taste, it’s feasible to tread an alternate path and implement a flexible view module by appealing to the functionality brought by Decorators. In the follow up I’ll be covering the inner workings of precisely this approach, so don’t miss it!

Image via Fotolia

Flexible View Manipulation

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • http://www.fractalserver.com Manuel H.

    Hi Alejandro,
    Or you write down all your articles in a book, or I’ll do! Thank you very much, I’m your biggest fan. You are rising the PHP development bar to a real professional level.

    • Alex Gervasio

      Hi Manuel.
      Well, thanks for the sweet comments indeed. About your book proposal, how about coauthoring the book in question? I guess that would be a pretty amusing experience, don’t you think so?
      Keep up the good work :)

  • Selorm

    Good tutorial as always… wondering if u guys are gonna write a tutorial on the Yii Framework.??

    • Alex Gervasio

      Hello Selorm,
      Thanks for the kind comments. Regarding your question on Yii, frankly I’m not aware of the topics that will be covered by other authors from now on. In my case, at least for the moment, I’m not planning to write about Yii, even though I consider it overall, with its ins and outs, of course, a good framework. Maybe someone else is cooking a post in Yii behind the scenes or maybe is queued in PHPMaster’ stack already. To make sure, you may want to contact Tim, our venerable editor. Thanks :)

  • Alex Fraundorf

    Great article as always Alejandro. I wish your articles had been around when I was learning MVC! I’ll be looking forward to the second part.

    • Alex Gervasio

      Glad to hear that Alex. Thanks for the positive feedback.

  • Evgeni Ivanov

    As usual really nice article!Looking forward to the second part.

    • Alex Gervasio

      Nice to hear from you again Evgeni. Thanks for the kind comments.

  • fomigo

    Thank you, Alex.
    I really love your posts!

    • Alex Gervasio

      Hey fomigo,
      Thanks for the positive comments. They cheer me up :)

  • Alex Garcia

    Hi Alex!
    I just implemented a Company management tree structure in C++ using the composite design pattern a couple days ago, where consists on supervisors and workers sharing a common behavior. Supervisors can manage other supervisors or workers under them. Supervisor represents my composite class. Your write up “me vino como anillo al dedo”. Thank you very much Alejandro! I am also your biggest fan!
    p.s: For the website editor- there is some format issues on the default.php and Testing snippets. Also, for those with lazy eye, the View class on the Composite implementation needs to specify namespace in line
    02: namespace Library/View;
    ..just minor details

    • Alex Gervasio

      Hey Alex,
      Glad to know the post was useful, and you were able to tweak without much fuss the content and make it fit your personal needs. Considering your project is developed in C++, that speaks pretty clearly about why is so damn important to grasp the key concepts that surround the use of several OOP principles, patterns and well-trusted paradigms, independently of the language you’re dealing with. Yep, as most of the patterns that make use of some form of recursive injection behind the scenes, Composites are somewhat tangled to implement at first, but once you get them rolling, they’re a pretty fancy solution for processing tree structures by using Composition over Inheritance.
      Regarding the format issues you point out, I’ll try to reach Tim, so he can get them fixed up ASAP. Thanks for the feedback.

  • http://faizalpribadi.github.com Faizal Pribadi

    Check You’re Implementation ViewInterface
    Wrong Name For Set Variable
    It’s Not Big Problem , But Thanks For This :D

    • Alex Gervasio

      Thanks Faizal for catching that. Somehow I misspelled the variable name in the view implementation.

  • Les

    Been using the Composite for quite a number of years now myself and I’ve found it to be extremely flexible in how you can put just about any page together from “nothing” (little scripting required).

    But I am being selfish by not making my code base public for all to use and learn from I must admit… possibly one day :)

    • Alex Gervasio

      Thanks for the comments Les. Totally agreed. While it may take some time to tame the driving logic of composites, once you get it they’re pretty nice for processing single/multiple objects through the same API. Plus, you don’t have to deal with the intrinsic burdens and oddities of Inheritance. Quite a big deal indeed.
      P.S. Be nice with the community and make your code base available for all. Can’t wait to see it :)

  • Samuca

    Can you provide the files ? Thanks

    • Alex Gervasio

      Hey,
      Unfortunately, there’s no a downloadable package for the files. Anyway, it’s really simple to create them directly from the code samples. The only additional component you should provide on your own is the autoloader, and certainly there’s a plethoric variety of them to pick up out there, including Symfony’s universal class loader https://github.com/symfony/ClassLoader/blob/master/ClassLoader.php. Thanks for the feedback.

  • http://www.perfect-soft.ir Alireza Rahmani Khalili

    hi how i can connect with u?

    • Alex Gervasio

      Hey Alireza,
      Nice to hear from you again mate :) Well, ask Tim, our gentle editor to provide you with my email address, or if you just don’t mind, let me reach you instead. Is your website’s contact form currently working? Let me know. Thanks!

  • http://www.perfect-soft.ir Alireza Rahmani Khalili

    it’s under construction, my email address AlirezaRahmani@live.com, i will be glad . tnx

  • Uncle Fred

    A lot of magic but very clever indeed. What tripped me was this line:
    return $field instanceof Closure ? $field($this) : $field;
    So that the place where Closure holding the anonymous function get executed by __invoke(). Since none of the anonymous functions actually use $this, we could potentially have it like so:
    return $field instanceof Closure ? $field() : $field;

    Love the write-up and off to reading the second part

    • Alex Gervasio

      Thanks for the kind comments Fred. In fact, I deliberately decided to pass along an instance of the view each time the anonymous function gets executed, “just in case” the function in question needs to further use the view in some form. Of course, doing so is entirely optional, so a more orthodox and tight implementation would definitively stick to the approach you suggests above.

  • Sebastiaan

    A warning about magic methods, they tent be slower then normal method calls.
    http://www.garfieldtech.com/blog/magic-benchmarks
    http://erosbence.blogspot.nl/2011/07/getters-setters-performance.html

    And can someone please tell me how hide that huge and useless popover widget-bar at the top of this site??

    • Alex Gervasio

      Hey Sebastiaan,
      Yep, definitively there’s a pretty valid point in your opinion, but I don’t think being a little bit pragmatic and using just a few magic methods here and there will downgrade performance (sounds like premature optimization :) IMO, the weakest point is that they tend to make APIs a lot less explicit and declarative. It’s a sort of tradeoff that should be evaluated in a “per use case” basis.
      And hey, you can get rid of the fancy navbar turning JavaScript off (but you’ll miss the joys of progressive enhancement) Another tradeoff you’ll have to deal with :). Thanks for the comments.

  • http://www.flipflops.org John

    Hi – just wanted to say I always enjoy your articles. It’s good to see code examples that tackle actual problems and not just nicely abstracted solutions that don’t ever quite fit into the real world. I use these kind of structures regularly, but it’s interesting to see an example with namespaces and closures.
    Cheers

    • Alex Gervasio

      Thanks John for the positive feedback. I always try to showcase pretty realistic use cases to make a certain point, but sometimes it’s rather hard to accomplish that 100%. Anyway, it’s worth trying out :)

  • Lee

    Thanks for this. I’m using just the first class there ‘View’ in my WordPress plugin experiments. Perfect little helper…and __get() and __unset() makes references to $field when I think you mean $name… Thanks for sharing your knowledge.

    • Alex Gervasio

      Nice to hear that. Thanks.

  • http://blog.mindplay.dk Rasmus Schultz

    Great article!

    Just one small point of criticism: using the magic __get() and __set() methods doesn’t feel right for something like this. Your view-dictionary values are not properties, and should not use property-syntax – these will light up red in most IDEs.

    Implementing the ArrayAccess interface is more appropriate in this case, I think – using array-syntax will not cause things to light up red in an IDE.

    The view-dictionary is rightfully a collection of named values, and this way, you wouldn’t experience collisions with actual properties on the View objects, should you need to add any. (the getTemplate() and setTemplate() accessor-methods could be more rightfully implemented as a virtual property.)

    Just my two cents.

    Very happy to see somebody teaching real programming with PHP and not just hacks!