PHP
Article
By Alejandro Gervasio

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

By Alejandro Gervasio

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.

--ADVERTISEMENT--

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

More:
Recommended
Sponsors
The most important and interesting stories in tech. Straight to your inbox, daily. Get Versioning.
Login or Create Account to Comment
Login Create Account