PHP: Rendering Web Pages Using the Composite View Design Pattern

Welcome to the conclusion of a five-part series on the Composite View design pattern. This article will focus on a way to make use of this design pattern when you’re building dynamic web pages. It involves a simple two-step rendering process.

As you probably know, one of the great commandments of good object-oriented programming says that whenever possible, Composition must be used over Inheritance, as the latter is an overrated way of reusing code. While it’s fair to admit that this principle should be used with due caution and, for obvious reasons, applied in the appropriate situations, there’s a case where it really shows all of its splendor.

Yes, as the name of this article suggests, this time I’m talking about the implementation of Composite View, a flexible design pattern derived from its cousin Composite. When used for web development, Composite View allows you to manipulate single templates (in most cases in the form of HTML pages) and collections of them via the same interface.

Naturally, if you’ve already read all of the preceding tutorials in this series, it’s probable that you now have a clear idea of how to create a few composite view classes with PHP, and how to use them for rendering dynamic web pages with a single method call. I discussed in detail how to accomplish this in the previous installment.

Even though rendering several templates through only one class method is by far the major strength of a “typical” Composite View, it’s also possible to use the pattern in a slightly different manner and obtain nearly the same results, at least when creating dynamic web pages. To demonstrate how to create this interesting variation of the pattern, in this last chapter of the series I’m going to utilize the sample classes defined previously to generate a basic (X)HTML document, where each of its sections will be rendered individually before being embedded into a master layout.

Want to see how this will be done in a few simple steps? Then start reading right now!         

A brief look at the composite view classes defined previously

As I said in the introduction, it’s feasible to use the composite view classes created in previous chapters of this series to build a dynamic (X)HTML page by using a two-step rendering process. But, before I start demonstrating how to achieve this, I’d like to spend a few moments reintroducing the definitions of the classes.

With that said, here’s the abstract parent class, tasked with modeling the structure and behavior of generic view objects:

(AbstractView.php)


<?php

abstract class AbstractView
{
    protected $_template = ‘default.php’;
    protected $_properties = array();

    // constructor
    public function __construct($template = ”, array $data = array())
    {
        if ($template !== ”) {
            $this->setTemplate($template);
        }
        if (!empty($data)) {
            foreach ($data as $name => $value) {
                $this->$name = $value;
            }
        }
    }
   
    // set a new view template
    public function setTemplate($template)
    {
        $template = $template . ‘.php’;
        if (!file_exists($template)) {
            throw new ViewException(‘The specified view template does not exist.’);  
        }
        $this->_template = $template;
    }
     
    // get the view template
    public function getTemplate()
    {
        return $this->_template;
    }
     
    // set a new property for the view
    public function __set($name, $value)
    {
        $this->_properties[$name] = $value;
    }

    // get the specified property from the view
    public function __get($name)
    {
        if (!isset($this->_properties[$name])) {
            throw new ViewException(‘The requested property is not valid for this view.’);     
        }
        return $this->_properties[$name];
    }

    // remove the specified property from the view
    public function __unset($name)
    {
        if (isset($this->_properties[$name])) {
            unset($this->_properties[$name]);
        }
    }
   
    // add a new view (implemented by view subclasses)
    abstract public function addView(AbstractView $view);
   
    // remove a view (implemented by view subclasses)
    abstract public function removeView(AbstractView $view);
   
    // render the view template
    public function render()
    {
        if ($this->_template !== ”) {
           extract($this->_properties);
           ob_start();
           include($this->_template);
           return ob_get_clean();
        }
    }
}// End AbstractView class

 

<?php

class ViewException extends Exception{}

Since the driving logic of the above abstract parent class was discussed in depth before, I’m not going to waste your time (and mine) explaining again how it works. Instead, I suggest you look at the definitions of the following two classes, which are responsible for handling view objects collectively and individually. Here they are:

(View.php)


<?php

class View extends AbstractView
{
    protected $_views = array();
       
    // factory method (chainable)
    public static function factory($view, array $data = array())
    {
        return new self($viewfile, $data);
    }
   
    // add a new view object
    public function addView(AbstractView $view)
    {
        if (!in_array($view, $this->_views, TRUE)) {
            $this->_views[] = $view; 
        }
        return $this;
    }
   
    // remove an existing view object
    public function removeView(AbstractView $view)
    {
        if (in_array($view, $this->_views, TRUE)) {
            $views = array();
            foreach ($this->_views as $_view) {
                if ($_view !== $view) {
                    $views[] = $_view;
                }
            }
            $this->_views = $views;
        }
        return $this;
    }
   
    // render each partial view (leaf) and optionally the composite view
    public function render()
    {
        $innerView = ”;
        if (!empty($this->_views)) {
            foreach ($this->_views as $view) {
                $innerView .= $view->render();
            }
            $this->content = $innerView;
        }
        $compositeView = parent::render();   
        return !empty($compositeView) ? $compositeView : $innerView;
    }  
}// End View class

 

(Partial.php)


<?php

class Partial extends AbstractView
{
    // throw an exception as a partial view (leaf) cannot add another view
    public function addView(AbstractView $view)
    {
        throw new ViewException(‘A partial view cannot add another view.’);  
    }
   
    // throw an exception as a partial view (leaf) cannot remove another view
    public function removeView(AbstractView $view)
    {
        throw new ViewException(‘A partial view cannot remove another view.’);  
    }   
}// End Partial class

From the above code samples, it’s clear to see how the concrete “View” class is capable of rendering the templates associated with single and multiple view objects through a unique method. Again, this puts in evidence how the Composite View pattern makes a clever use of Composition, instead of relying heavily on the benefits provided by Inheritance.

And now that you’ve learned how the earlier sample classes do their business, I’m going to show the source code of the autoloader created in the preceding chapter. It can be used for lazy-loading classes  via the SPL stack offered natively by PHP.

Here’s how the pertinent autoloader was originally created: 

(Autoloader.php)


<?php

class Autoloader
{
    private static $_instance;
   
    // get the Singleton instance of the autoloader
    public static function getInstance()
    {
       if (!self::$_instance) {
           self::$_instance = new self;
       }
       return self::$_instance;
    }
   
    // private constructor
    private function __construct()
    {
        spl_autoload_register(array($this, ‘load’)); 
    }
   
    // prevent cloning instance of the autoloader
    private function __clone(){}
    
    // autoload classes on demand
    public static function load($class)
    {
        $file = $class . ‘.php’;
        if (!file_exists($file)) {
            throw new ClassNotFoundException(‘The file ‘ . $file . ‘ containing the requested class ‘ . $class . ‘ was not found.’);
        }
        include $file;
        unset($file);
        if (!class_exists($class, FALSE)) {
            throw new ClassNotFoundException(‘The requested class ‘ . $class . ‘ was not found.’);
        }
    }  
}// End Autoloader class

 

<?php

class ClassNotFoundException extends Exception{}

Well, you’ll have to agree with me that the implementation of the above “Autoloader” class is very easy to follow, as it simply uses the SPL stack for loading classes on demand without having to use multiple PHP includes. That was simple to code and read, wasn’t it?

So far, so good. Now that I’ve reintroduced all of the sample classes defined so far, it’s time to demonstrate how to use them together in a truly creative way. We’re going to create a dynamic web page by using the aforementioned two-step rendering process.

That’s the topic that I plan to discuss in the following section, so click on the link that appears below and keep reading.

{mospagebreak title=Creating some basic web page sections}

As I said in the introduction, it’s fairly easy to use the composite view classes that you just saw in a slightly different way, and build from scratch a web page with sections that are rendered individually before being embedded into a general layout.

To illustrate more clearly how to accomplish this, first it’s necessary to create the corresponding web page sections, along with the mentioned layout. Take a look at the code below:

(header.php)

<div id="header">
    <h2><?php echo $content;?></h2>
</div>

 

(body.php)

<div id="body">
    <h2><?php echo $content;?></h2>
</div>

 

(footer.php)

<div id="footer">
    <h2><?php echo $content;?></h2>
</div>

 

(layout.php)

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>Master Layout</title>
    </head>
    <body>
        <?php echo $header->render();?>
        <?php echo $body->render();?>
        <?php echo $footer->render();?>
    </body>
</html>

As the above code fragments show, the web page sections are simple PHP files that print on screen the values assigned to their $content property. On the other hand, the master layout renders the sections via the corresponding “render()” method, in this way building a “well-formatted” web page.

While the presentation logic included in the structure of the layout file makes it pretty easy to guess how the containing web page will be generated from top to bottom by using the previous composite view classes, the best way to understand this process is by means of a concrete example. Therefore, I’m going to code that example for you, which will wrap up the entire series.     

Rendering an entire web page with a two-step rendering process

If you want to see how the templates defined above can be used by the  composite view classes defined previously to create an entire web page, the following code snippet should satisfy your curiosity. Check it out:

<?php

try {
    // include autoloader class and grab an instance of it
    require_once ‘Autoloader.php’;
    $autoloader = Autoloader::getInstance();
   
    // create the header section
    $header = new Partial(‘header’);
    $header->content = ‘This is the header section’;
   
    // create the body section
    $body = new Partial(‘body’);
    $body->content = ‘This is the body section’;
   
    // create the footer section
    $footer = new Partial(‘footer’);
    $footer->content = ‘This is the footer section’;
   
    // create the master layout
    $layout = new View(‘layout’);
    $layout->header = $header;
    $layout->body = $body;
    $layout->footer = $footer;
    echo $layout->render();  
}
catch (Exception $e) {
    echo $e->getMessage();
    exit();
}

As the above script shows, each section of the web page is rendered by creating different instances of the “Partial” class, which are assigned later on as properties of its counterpart “View.” At the end of this process, the whole page is echoed to screen via the “render()” method, which generates the following output: 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>Master Layout</title>
    </head>
    <body>
        <div id="header">
          <h2>This is the header section</h2>
         </div>
         <div id="body">
           <h2>This is the body section</h2>
          </div>
         <div id="footer">
             <h2>This is the footer section</h2>
          </div>
   </body>
</html>

The previous example demonstrates how to build a web page in a snap; indeed, when it comes to flexibly creating dynamic (X)HTML pages, a typical implementation of the Composite View pattern will fit the requirements of most use cases. However, there are times when it’s necessary to utilize an approach similar to the one shown before (called in programming jargon the “two-step view” design pattern). So, if you’re planning to use composite classes to generate your web pages, feel free to pick the method that best suits your needs.

Final thoughts

We’ve come to the end of this series. Hopefully, the code samples shown in its five articles have provided you with the right pointers to start using the Composite View design pattern within your own object-oriented PHP applications. Even though at first glance the driving logic of the pattern seems to be somewhat difficult to grasp, learning it is really worthwhile, as the paradigm is one of the most representative examples where the functionality of Composition can be used for simplifying the manipulation of multiple view objects and their associated templates.

Now that you’ve learned the theoretical concepts that surround the implementation of the Composite View design pattern, go ahead and put it to work for you. You won’t be disappointed with the results.

See you in the next PHP development tutorial!

[gp-comments width="770" linklove="off" ]
antalya escort bayan antalya escort bayan