Home arrow PHP arrow PHP: Creating Single View Objects with the Composite View Design Pattern

PHP: Creating Single View Objects with the Composite View Design Pattern

In this third part of a series on the Composite View pattern, I develop a concrete class derived from the abstract parent built previously. This new class will be responsible for creating simple view objects.

TABLE OF CONTENTS:
  1. PHP: Creating Single View Objects with the Composite View Design Pattern
  2. Handling single view objects
By: Alejandro Gervasio
Rating: starstarstarstarstar / 2
August 24, 2010

print this article
SEARCH DEV SHED

TOOLS YOU CAN USE

advertisement

The tandem composed of the Composite and Decorator design patterns offers an example that shows where the use of Composition can help in building flexible applications. While decorators are normally used for extending the functionality of objects that are of the same type without having to appeal to Inheritance, Composites provide an elegant and efficient paradigm that allows programmers to manipulate single objects and collections of them through the same interface.

There’s a plethora of situations where Decorators are utilized successfully in the development of PHP-based programs, and more specifically in the construction of versatile user interfaces on web pages. But what about Composites? Well, there's a relative of Composite called “Composite View,” which can be used for rendering single and multiple (X)HTML templates in a very flexible fashion. Simply put, client code consuming a composite view class will be able to manipulate web page sections, and even entire (X)HTML documents, via the same set of methods without being aware of this. That’s a good example of encapsulation, right?

If you've already read previous parts of the series, then you've seen a couple of concrete ways to implement the Composite View pattern. I started by creating a simple hierarchy of composite view classes, comprised of an abstract parent that defined the structure and behavior of generic view objects. I then created a concrete subclass, which was responsible for handling these objects individually and collectively via a unique rendering method.

To complete this hierarchy, though, it’s necessary to create an additional class. It will be tasked with creating single view objects. So, in this third installment of this series I’m going to show you how to build such a class, which will be an approachable process, believe me.

Now, it’s time to get rid of the dull theory and continue exploring the benefits of using the Composite View pattern in PHP. Let’s go!

Review: a quick summary of the sample classes developed so far

Just in case you still haven’t read the tutorial that precedes this one, where I showed how to create a concrete composite view class derived from the abstract parent mentioned in the introduction, below I included for you the definitions corresponding to these sample classes. This way, you can quickly grasp how they work.

First, here is the abstract parent, which is 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{}

If you study the above “AbstractView” class in detail, you’ll realize that it’s nothing but a simple container that stores the properties assigned to a generic view object, including its associated template file. Of course, its “render()” method is responsible for rendering the template, but only for a single object. However, a typical implementation of a Composite View should be able to render single and multiple templates through the same interface. How can this be done?

Well, the following concrete subclass performs this task in a fairly straightforward fashion. Look at it, please:

(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

There you have it. As you saw before, the previous “View” class is capable of rendering indiscriminately a single template or a collection of them, thanks to the implementation of the inherited “addView()” and “removeView()” methods.

Even though at first glance, a composite view class like the one defined above seems to be pretty pointless, the truth is that its functionality can be cleverly exploited to render multiple web page sections and complete (X)HTML documents via a single method call. But in fact I’m getting ahead of myself, since the full details of how to accomplish this will be covered in upcoming parts of this series.

For the moment, the next thing we must do is create a concrete implementation of the previous “AbstractView” class that allows us to create single view objects in a truly painless way. Precisely this process will be discussed in the next section, so to learn more about it, click on the link below and keep reading.



 
 
>>> More PHP Articles          >>> More By Alejandro Gervasio
 

blog comments powered by Disqus
escort Bursa Bursa escort Antalya eskort
   

PHP ARTICLES

- Hackers Compromise PHP Sites to Launch Attac...
- Red Hat, Zend Form OpenShift PaaS Alliance
- PHP IDE News
- BCD, Zend Extend PHP Partnership
- PHP FAQ Highlight
- PHP Creator Didn't Set Out to Create a Langu...
- PHP Trends Revealed in Zend Study
- PHP: Best Methods for Running Scheduled Jobs
- PHP Array Functions: array_change_key_case
- PHP array_combine Function
- PHP array_chunk Function
- PHP Closures as View Helpers: Lazy-Loading F...
- Using PHP Closures as View Helpers
- PHP File and Operating System Program Execut...
- PHP: Effects of Wrapping Code in Class Const...

Developer Shed Affiliates

 


Dev Shed Tutorial Topics: