Patterns for Flexible View Handling, Part 2 – Using Decorators

Share this article

For years, we’ve been so busy discussing the virtues and drawbacks of the model/controller tandem that we’ve overlooked the role of views, denigrating them to a level of clunky HTML templates. Though the origins of MVC isn’t rooted in the OOP paradigm per se, most of the implementations currently available in the wild rely on the use of classes. In short, this means that if our own arrogant nature leads us believe the “view = HTML template” equation is valid, we’ll be failing to see the benefits of thinking of views as rich objects carrying state and behavior which can be manipulated through the logic of several design patterns.

In a humble attempt to avoid being misjudged for just babbling, in the first installment I implemented a customizable view module from scratch where views were conceptually designed up front as POPOs and the module was given the ability to recursively parse multiple view objects via the same API, hence honoring a typical implementation of the Composite pattern.

Indeed, processing individual views and composite ones through the reins of a unified API provides a lot of flexibility as it allows us to render tree structures (in most cases chunks of HTML, but it could just as easily be anything else a browser can digest) without having to unnecessarily pollute client code with smelly conditionals, an ominous sign of a breaking the Open/Closed principle.

It’s also feasible to manipulate views in fairly flexible fashion by appealing to the niceties of a few other patterns as well, including the rather underrated Decorators. If you’re wondering in what parallel universe Decorators get along with views, in this part I’ll be showing how to put them to work side by side in nice orchestration to bring to life yet another view module.

Pipelining Functionality at Runtime – Bringing Decorators to the Table

Here’s a quick test you can try on your work mates: catch them off guard by asking them where Decorators can be used in PHP. They’ll probably react by saying something like “well, Zend Framework implements form decorators, and PHPUnit also uses them… and Symfony used to drop them somewhere, but I’m not quite sure where actually.” In fact, this is probably what many of us will mumble in such situations since Decorators aren’t precisely creatures with a prolific existence in the world of PHP.

Regardless, the benefits they provide of the box are pretty remarkable. They allow us to attach functionality to a given component at runtime by injecting it into a few other wrappers that share the same interface.

It sounds like an obscure concept? Let’s try an example where an HTML element is modeled as a renderable structure implementing the following contract:

<?php
namespace LibraryHtml;

interface HtmlElementInterface
{
    public function getText();
    public function render();
}
<?php
namespace LibraryHtml;

class Span implements HtmlElementInterface
{
    protected $text;
    
    public function __construct($text) {
        if (!is_string($text) || empty($text)) {
            throw new InvalidArgumentException(
                "The text of the element must be a non-empty string.");
        }
        $this->text = $text;
    }
    
    public function getText() {
        return $this->text;
    }
    
    public function render() {
        return "<span>" . $this->text . "</span>";
    }
}

Building a class that dumps a single <span> element won’t add a new notch to my developer belt, but it’s useful for showing how to exploit the benefits of decorators.

Let’s say that we need to append some extra functionality to the object that renders the element or, in a broader range, to any other implementer of the HtmlElementInterface interface. To do so, we should first drop the common implementation inside the boundaries of an abstract decorator, like this one:

<?php
namespace LibraryHtml;

abstract class AbstractHtmlDecorator implements HtmlElementInterface
{
    protected $element;

    public function __construct(HtmlElementInterface $element) {
        $this->element = $element;
    }

    public function getText() {
        return $this->element->getText();
    }

    public function render() {
        return $this->element->render();
    }
}

With the AbstractHtmlDecorator class making use of delegation, it’s easy to subclass a few concrete decorators that perform some additional tasks on the injected HTML element behind the scenes. Moreover, the ones below rely on this concept for wrapping the element’s markup inside some <p>, <div>, and <section> tags:

<?php
namespace LibraryHtml;

class DivDecorator extends AbstractHtmlDecorator
{
    public function render() {
        return "<div>" . $this->element->render() . "</div>";
    }
}
<?php
namespace LibraryHtml;

class ParagraphDecorator extends AbstractHtmlDecorator
{
    public function render() {
        return "<p>" . $this->element->render() . "</p>";
    }
}
<?php
namespace LibraryHtml;

class SectionDecorator extends AbstractHtmlDecorator
{
    public function render() {
        return "<section>" . $this->element->render() . "</section>";
    }
}

Admittedly, the role that each decorator plays is rather banal. Still, let’s see how they work:

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

$div = new DivDecorator(
    new ParagraphDecorator(new Span("Welcome to SitePoint!"))
);
echo $div->render();

$section = new SectionDecorator(
    new DivDecorator(
        new ParagraphDecorator(new Span("Welcome to SitePoint!"))
    )
);
echo $section->render();

Constructing multiple pipelines of decorators at runtime in order to render several markup structures is a straightforward process. The sequence in which each decorator is assembled can be altered without much fuss, and it’s possible to appeal to this trick and generate disparate portions of HTML on the fly, each one exposing a different semantic meaning.

Although the earlier example is illustrative, it falls short when it comes to treading the road of production, since generating large chunks of markup programmatically with this method is pointless. You’re probably wondering how we can use decorators in a more useful fashion other than rendering just a few naive HTML elements.

Using Decorators in a More Pragmatic Fashion – Setting up an Extensible View Module

We could model a base view class and, in turn, attach to it a bunch of decorators implementing the same interface which, among other neat things, would let us dynamically generate fancy web page headers, footers, and even outer layouts. Implementing a customizable view module that exploits decorators is a lot easier than one might think, as the whole process can be boiled down to creating the aforementioned base view class and then extending its functionality through one or more decorators according to more refined needs.

To get the module working, I’m going to use the same View class I wrote in the first part which implemented a segregated ViewInterface interface. With this component already coded, we can focus on a few decorators which will be responsible for rendering custom headers, footers, and layouts. Here’s the hierarchy of decorators to perform these tasks:

<?php
namespace LibraryView;

abstract class AbstractViewDecorator implements ViewInterface
{
    const DEFAULT_TEMPLATE = "default.php";
    protected $template = self::DEFAULT_TEMPLATE;
    protected $view;

    public function __construct(ViewInterface $view) {
        $this->view = $view;
    }
    
    public function render() {
        return $this->view->render();
    }
    
    protected function renderTemplate(array $data = array()) {
        extract($data);
        ob_start();
        include $this->template;
        return ob_get_clean();
    }
}
<?php
namespace LibraryView;

class OuterViewDecorator extends AbstractViewDecorator
{
    const DEFAULT_TEMPLATE = "layout.php";
    
    public function render() {
        $data["innerview"] = $this->view->render();
        return $this->renderTemplate($data);
    }
}
<?php
namespace LibraryView;

class HeaderViewDecorator extends AbstractViewDecorator
{
    const DEFAULT_TEMPLATE = "header.php";
    
    public function render() {
        return $this->renderTemplate() . $this->view->render();
    }
}
<?php
namespace LibraryView;

class FooterViewDecorator extends AbstractViewDecorator
{
    const DEFAULT_TEMPLATE = "footer.php";
    
    public function render() {
        return $this->view->render() . $this->renderTemplate();
    }
}

Each decorator is a plain wrapper for injected view objects which in turn override the base render() method in order to add some specific web page sections to the objects’ templates. The rendering process should be even easier to understand if I pitched some testable examples. So, suppose we’ve defined a couple of skeletal templates, called partial.php and layout.php, which look as follows:

<h2><?php echo $this->heading;?></h2>
<p><?php echo $this->content;?></p>
<!doctype html>
<html>
 <head>
  <meta charset="utf-8">
  <title>My fancy web page</title>
 </head>
 <body>
  <header>
   <h1>A sample header</h1>
  </header>
  <section>
   <?php echo $innerview;?>
  </section>
  <footer>
   <p>A sample footer</p>
  </footer>
 </body>
</html>

Now, if we ever need to embed the partial straight into the outer layout, the process would be reduced to coding the following snippet:

<?php
$view = new View("partial");
$view->heading = "This is the sample heading line";
$view->content = "This is the sample content";

$page = new OuterViewDecorator($view);
echo $page->render();

That was a breeze indeed. But we’re not done yet; there’s a few more nifty things to play around with. How about rendering a similar HTML5 document, this time by attaching the header and the footer at runtime? Well, let’s then define the templates bound to the corresponding decorators, namely header.php and footer.php:

<!doctype html>
<html>
 <head>
  <meta charset="utf-8">
  <title>My fancy web page</title>
 </head>
 <body>
  <header>
   <h1>A sample header</h1>
  </header>
<footer>
   <p>A sample footer</p>
  </footer>
 </body>
</html>

With the templates in place, we can now spawn a view object containing the partial, and then drop the decorators in the desired sequence, as following:

<?php
$view = new View("partial");
$view->heading = "This is the sample heading line";
$view->content = "This is the sample content";

$page = new FooterViewDecorator(new HeaderViewDecorator($view));
echo $page->render();

While I have to admit that the process of rendering a well-formed HTML document is in this case a little bit more cumbersome and tedious than just handling a single template with some PHP code scattered through it, in a nutshell it shows how to exploit the functionality provided by a few simplistic decorators in the implementation of a customizable view module. Furthermore, considering the module’s inherent flexibility, it’s fairly easy to make it a little bit richer by pushing into its internals some extra decorators, others than the ones just implemented.

If you’re feeling bold and want to tackle that challenge, you’ll get a break on sharpening your coding skills for free.

Final Thoughts

Very few will disagree that the Composite and Decorator patterns are among the most blatant examples of the “Favor Composition over Inheritance” mantra in action. Despite of this, they’re still rather overlooked paradigms in PHP limited to the dark corners of just a few popular frameworks.

Even so, leveraging their abilities and employ them for manipulating view objects in a flexible manner is everything but complex. In this case, the modules showcased in this roundup are just elementary examples, a far cry away for being production ready; hopefully they should be illustrative enough for making a valid point and encouraging the use of the patterns in a more multifaceted way.

Image via Fotolia

Alejandro GervasioAlejandro Gervasio
View Author

Alejandro Gervasio is a senior System Analyst from Argentina who has been involved in software development since the mid-80's. He has more than 12 years of experience in PHP development, 10 years in Java Programming, Object-Oriented Design, and most of the client-side technologies available out there.

Expert
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week