Object Interaction in PHP: Introduction to Composition

Composition is an important concept in PHP. It occurs when an object creates another object; that is, the first object completely possesses the second object. In this article (the first of two parts), Alejandro Gervasio explains composition, and shows some examples to illustrate his points.

Introduction

From a PHP programmer’s point of view, there are many interesting ways that objects can interact with each other within an application. Used extensively across well-structured projects, inheritance is one of the major foundations of the object-oriented paradigm. It allows a  basic and generic functionality to be implemented on a base class, and provide generic methods and properties that are inherited by any derived subclass, in order to “fine-tune” the child classes to suit more specific purposes. If you’ve been working for a while with database abstraction classes, to cite an illustrative example, probably you know what I’m talking about here.

Aside from inheritance, and its partner, polymorphism, we can find other situations where objects are involved in some kind of interaction. Definitely, one concept that rapidly comes to my mind is that of aggregation. If you’re unaware of its existence, you’re missing something really relevant, trust me.

Generally speaking, aggregation occurs when one object uses the functionality of another object to satisfy its own purposes. Although this sounds a bit egotistical, the truth is that aggregation is an extremely powerful concept, used very frequently in object-oriented environments. Commonly, there are situations where one object, such as a database result set processor, needs to have database connectivity within its scope. This is a common case where this last object performs a query against a database, using the connectivity given by the first object, which is usually passed to the second as a constructor parameter.

Definitely, this might sound familiar to you, if you work with objects in PHP on a daily basis. However, the subject is really very far from being fully covered. I hope you’re wondering why. What about having an object that creates another object, that is, the first object completely possesses the second? Yes! Now we are talking about a concept often known as composition.

So, do we have yet another big player in the OOP arena? You bet. What’s more, composition plays a very important role in many situations, where the interaction between objects is carried out in a carefully planned way. Thus, the subject deserves an indepth examination. That’s what I’ll do in the course of this article. I’ll offer a short introduction to the theory of composition, as well as its possible implementation in different practical situations. I guess that you’re ready to learn more about it, right? Okay then, let’s not waste any more time in preliminaries.

{mospagebreak title=Composition: some theory ahead}

As I mentioned before, composition is very a useful thing when applied in production environments. But, let’s dig a bit into its theory, in order to understand how can it be implemented in real-world projects. I promise it will be short.

Composition happens when one object directly creates a second object. This means that the original object is responsible for the “birth” of the second, to express it in a comprehensible way. If we think about the concept, this condition can happen many times during the execution of PHP applications. However, sometimes, when we’re working extensively with objects here and there, we might get quickly confused by having so many definitions to deal with.

As a general rule, particularly in terms of practical implementation, it’s important to know how to define a relationship between objects. Therefore, we might say that one object “composes” another one when this object is not capable of living without the other. Let’s put it in a practical way. Having two objects A and B, if our object B simply “passes away” when object A dies, then we say that object B composes to A.

Explained in that manner, you shouldn’t have a problem understanding composition. In general terms, composition is easier to handle under certain conditions where many classes are involved. The main reason for having this advantage is that, most of the time, we know which class is directly responsible for creating a specific object. The process makes it a lot easier to track the existence and usage of an object, since one particular class is directly generating another object.

Hopefully, we’ve grasped the goodies of composition’s theory, in order to gain an intimate grounding in PHP object interaction. However, I know that you’re hungry for code. Also, I know that you want some practical examples right now! Fine, relax, that’s coming. Theory is good and instructive, but we need to show composition in action, in order to taste its real power. So, just let’s flip the page and illustrate with an example of how composition works.

{mospagebreak title=Composition in a practical sense: a basic example}

As a introduction to composition in PHP, we’ll see a rather basic example that shows how one object composes another one. Since we’re speaking about object interaction, we need at least two objects to work with. So, to properly understand the basics of composition, let’s define two classes that comes handy to clarify any possible question.

The first class that we’ll define for our example is simply a “Page” class, which shows several methods for building a simplistic Web page. Based on the classic page schema composed of  “Header,” “Body” and “Footer” sections, the class presents a specific method to create each one of them. Here’s how our “Pager” class looks:

class Page {
    var $title;
    var $html;
    function Page($title=’Default Page’){
        $this->title=$title;
       
$this->html=”;
    
}
    
function makeHeader($header){
       
$this->html.=’<html><head><title>’.
         $this->title.’</title></head><body>’.$header;
   
}
    function makeBody($content=array()){
        return new Table($this,$content);
    }
    function makeFooter($footer){
        $this->html.=$footer.’</body></html>’;
    }
    function display(){
        return $this->html;
    
}
}

As you can see, the class is very simple and clear to understand. As mentioned before, it presents four methods concerned with building a web page, defined as follows: “makeHeader()”, makeBody()”, “makeFooter()” and finally “display()”, which simply returns the complete HTML markup to be dumped directly to the browser.

The “Page” class contains only two data members, necessary to generate the entire page: $title and $html. As you might guess, the first property will be used to display the page’s title, while the second will store the progressive HTML output, to be finally echoed to the browser. In fact, there is not much to be said about the basic “makeHeader()” and “makeFooter()” methods, since they speak for themselves.

Because of their simplicity, we’ll just say that they take care of creating the header and footer page sections, and add a few regular tags to wrap up the content of each section, which is passed as an argument to every specific method. However, not everything is as boring as seems. If we take a closer look at the “makeBody()” method, we quickly realize that it’s quite special. Why? Well, the method accepts a single parameter, $content that is defined as an array structure, in order to generate the main section of the page

But, it’s doing something else. Notice that it’s returning a new object called “Table”, as we can appreciate in the following line:

return new Table($this,$content);

This looks very interesting. Has it caught your attention? Fine. Here we have a “Page” class which is directly creating an instance of another “Table” object. Given this condition, we can say that the “Table” object composes the “Page” object. Pretty good, right? Just ask yourself the question previously mentioned: what happens to the “Table” object if the “Page” object ever dies? Certainly, it will die too, so it’s not capable of surviving on its own as an independent object. Thus, having answered that question, we have one object that composes another one.

Although the method is very simple, it shows clearly how we’ve defined the interaction process between the two objects. Notice that the newly created “Table” object accepts two parameters for its constructor: the first is the “Page” object itself, referenced as $this, while the second is the $content array used to include some content in the main section of the page.

The reason for creating a new “Table” object answers mostly to the example’s purposes. We want each “Page” object to create a “Table” object, which will render a color-alternated HTML table and display the contents in this container. Definitely, this page generator class isn’t suitable for application in real conditions, but it does its job by showing a clear situation where object composition takes place.

At this point, you’re probably wondering, what does the “Table” class look like? Okay, I thought you’d never ask. So, let’s have a look at its structure. Just click to the next page.

{mospagebreak title=The “Table” class: a simple row-color alternator}

Once we’ve deeply explored the definition for our “Page” class, it’s time to see how the “Table” class is defined, in order to complete the interaction process between the two classes. Thus, the “Table” class definition is listed below:

class Table {
    var $page;
    
var $content;
    
var $id;
    
function Table(&$page,$content){
       
$this->page=&$page;
       
$this->content=$content;
       
$this->id=’defaultID’;
    
}
    
function setId($id){
     
  $this->id=$id;
    
}
    
function build($colorA,$colorB){
       
$this->page->html.=’<table id=”‘.$this->id.’” width=”100%”>’;
       
$i=0;
       
foreach($this->content as $row){
           
$bgcolor=($i%2)?$colorA:$colorB;
     
         $this->page->html.=’<tr bgcolor=”‘.$bgcolor.’”>
            <td>’.$row.’</td></tr>’;
          
$i++;
       
}
       
$this->page->html.=’</table>’;
       
return $this->page->html;
   
}
}

As the above code shows, the unique function of this class is to build the main section of the page, generating a regular HTML table that alternates its row colors, to give a more polished presentation to the content. Data members are very descriptive and certainly don’t offer particular difficulties to understanding their meaning inside the context of the class, so let’s jump quickly into the explanation.

The first data member, that is $page, is the most relevant element since it represents a reference to an instance of the “Page” class. Remember that this object was already passed as an argument, at the time the “Table” object was created by the “Page” class. The two additional data members, $content and $id, refer the content to be included into the table and an ID table attribute, only for CSS styling purposes. Nothing unexpected, right?

Please notice how the constructor accepts the reference of the “Page” object and sets up the proper parameter initialization:

function Table(&$page,$content){
    $this->page=&$page;
    $this->content=$content;
    $this->id=’defaultID’;
}

However, a question comes up here: why are we passing a reference of a “Page” object inside the class? The reason should become clear if we briefly look at the other core method that the class presents: the “build()” method. It takes two incoming parameters, $colorA and $colorB respectively, to generate the alternating table rows, but the process directly assigns its output to the HTML code of the “Page” class, as shown below:

function build($colorA,$colorB){
   
$this->page->html.=’<table id=”‘.$this->id.’” width=”100%”>’;
    
$i=0;
   
foreach($this->content as $row){
       
$bgcolor=($i%2)?$colorA:$colorB;
       
$this->page->html.=’<tr bgcolor=”‘.$bgcolor.’”>
         <td>’.$row.’</td></tr>’;
       
$i++;
   
}
   
$this->page->html.=’</table>’;
   
return $this->page->html;
}

Can you see how this method modifies the $html property originally defined in the “Page” class? Just use the expression:

$this->page->html

and that’s it. Now, the final rendered table is appended as part of the overall page’s output, and then returned to the occurrence where the method was invoked. It’s really simple, don’t you think so?

Okay, now we have moved forward in order to gain a better understanding of composition in PHP. But there are still a couple of points left yet. Let’s see how we can implement these classes in a quick example, after listing the full source code for each class.

{mospagebreak title=Working with the classes: a quick example}

For those developers who want to play with the classes and get a more intimate knowledge of composition, here’s the full code for the classes reviewed here. First, our “Page” class:

class Page {
   
var $title;
   
var $html;
   
function Page($title=’Default Page’){
        
$this->title=$title;
       
$this->html=”;
   
}
   
function makeHeader($header){
       
$this->html.=’<html><head><title>’.
         $this->title.’</title></head><body>’.$header;
   
}
   
function makeBody($content=array()){
       
return new Table($this,$content);
   
}
   
function makeFooter($footer){
       
$this->html.=$footer.’</body></html>’;
    
}
   
function display(){
       
return $this->html;
   
}
}

And, second, the “Table” class:

class Table {
   
var $page;
   
var $content;
   
var $id;
   
function Table(&$page,$content){
       
$this->page=&$page;
       
$this->content=$content;
       
$this->id=’defaultID’;
   
}
   
function setId($id){
       
$this->id=$id;
   
}
   
function build($colorA,$colorB){
       
$this->page->html.=’<table id=”‘.$this->id.’” width=”100%”>’;
       
$i=0;
       
foreach($this->content as $row){
           
$bgcolor=($i%2)?$colorA:$colorB;
           
$this->page->html.=’<tr bgcolor=”‘.$bgcolor.’”>
             <td>’.$row.’</td></tr>’;
           
$i++;
       
}
       
$this->page->html.=’</table>’;
       
return $this->page->html;
    }
}

Also, here’s a possible implementation for the classes, in order to generate a basic page where its main content section includes a table with alternating row colors:

// include the classes
require_once ‘pageclass.php’;
require_once ‘tableclass.php’;

// instantiate a new Page object
$page=&new Page();

// make header
$page->makeHeader(‘<div>Header</div>’);

// set Table object parameters
$table=$page->makeBody(range(0,20));
$table->setId(‘maincontent’);

// build body table
$table->build(‘#ffcc00′,’#eeeeee’);

// make footer
$page->makeFooter(‘<div>Footer</div>’);

// display page
echo $page->display();

That’s all we need to make the classes work. As we usually do when working with classes, they’re included in the code. Then, we instantiate a “Page” object and build the page header, like this:

require_once ‘pageclass.php’;
require_once ‘tableclass.php’;

// instantiate a new Page object
$page=&new Page();

// make header
$page->makeHeader(‘<div>Header</div>’);

Now, we simply pass to the “Table” object a range of numbers from 0 to 20, just to populate the main section of the page with some data, and assign an ID attribute to the table:

// set Table object parameters
$table=$page->makeBody(range(0,20));
$table->setId(‘maincontent’);

Finally, we build the table, specifying the background colors that we want to be displayed alternately, generating the “footer” section, and displaying the page in the browser:

$table->build(‘#ffcc00′,’#eeeeee’);

// make footer
$page->makeFooter(‘<div>Footer</div>’);

// display page
echo $page->display();

Now, we can say that our job is finally finished. With the classes working seamlessly, it’s time to read the conclusions and look ahead to the next article in this tutorial about composition. Just follow me.

Wrapping up

In this first part of the series, we’ve tasted the power of composition in PHP, building two basic classes that demonstrate in a didactical way how one object composes another. This is useful for getting you started quickly working with other interesting aspects of object-oriented programming.

However, until now, we’ve worked merely with a couple of classes, which will hardly find their role in production environments. With this idea in mind, in the second part we’ll implement composition using a more realistic approach, since we’ll work with a fully functional MySQL abstraction class. Meanwhile, feel free to use the above developed code to introduce composition into your applications or develop your own classes. Until next time, stay tuned.

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