Object Interaction in PHP: Introduction to Aggregation, part 1

Aggregation in PHP allows one object to use another object. It’s a very powerful concept. This article, the first in the series, serves as an introduction to some of the things you can do with aggregation.

Introduction

In the growing world of Object Oriented Programming, the ways that objects interact with each other involve directly working with several concepts that deserve an in-depth look, in order to take advantage of their power in real-world applications. Particularly when we’re dealing with PHP, which is definitely an easy-to-grasp language compared to the harder learning curves of Java or C++ (among others), things are a lot more accessible, even if we go beyond the limits of working with procedural solutions.

At this point, most PHP users have already experienced the nice capabilities of PHP classes, by taking either the do-it-yourself road or reusing existing, well-trusted classes for managing larger projects. However, there are times where we need to work with several classes that require a strong interaction to efficiently accomplish a given set of tasks. So, this relationship immediately brings up a question: how do objects interact? Fortunately, the answer is quite straightforward, since this interaction can be defined within well-known OOP pillars.

The first trusted friend is inheritance, which offers a powerful mechanism for building class hierarchies, and allows us to address specific issues in a number of subclasses without the need to recreate the logic or functionality that already exists in the super class or parent class. That sounds very familiar, doesn’t it?

The next big ally of inheritance is polymorphism, which is defined as the ability of different classes to behave differently for the same operation. In programming lingo, we can say that two or more classes are sharing the same interface. Probably its most common application is found within database abstraction classes, where we’re using the same method (i.e. connect) for connecting to different databases systems.

So, that’s all there is to know about object interaction? Well, not yet. Aside from inheritance and polymorphism, there are a couple of interesting ways to make objects interact. Maybe you’ve been working with an object that uses another object, right? Or perhaps worked with an object that creates another one? Sure! We’re referring to the concepts of aggregation and composition. These two additional forms of object interaction are extremely useful, giving us undoubtedly strong foundations for deeply exploiting the power of object-oriented programming.

However, all of these things sound like a bunch of buzzwords, with no immediate use in Web applications, right? Well, not so fast. We have the power and need to use it. In this article, we’ll introduce ourselves to the process of implementing aggregation in PHP, to help us learn  more about the possible ways to make object interaction work for us. Let’s get started.

{mospagebreak title=What is aggregation?}

In the context of object interaction, aggregation simply refers to a situation where one object is passed to another object to perform some operations or methods within the object that called it originally. Usually, the second object is passed to the first one as a parameter using one of its member methods.

The great benefit of this is that, with the second object living happily in the first one, it’s possible to directly call its methods, allowing us to take advantage of its existing functionality, in order to fit the purposes of the first object.

In terms of practical application, aggregation is extremely important and powerful. After all, if I consider myself as an object A, which has a rather limited budget, but fortunately has a rich friend, that is, an object B, who is generously offering to me (at least temporarily) his credit cards, that is $B->offerCreditCards(), to buy that NAD state-of-the-art preamplifier, I’d feel very powerful!

If we talk about performance issues, the advantages of aggregation mainly come from its lower overload, since most of the time only one object is shared by other objects. However, this advantage might be discarded in the case of having a class for database connection shared by other multiple classes. You may run into difficulties if multiple database connections are established to the same server, causing a noticeable detriment to the system, particularly if your site is attracting many visitors.

Are you feeling as if it’s a bit confusing to handle objects here and there? It’s best to understand this by example. In the next section, we’ll define two simple classes to illustrate the concept of aggregation in a practical sense.

{mospagebreak title=Applying aggregation in a practical manner: defining sample classes}

Let’s define two basic classes and see how they can interact, in order to understand how aggregation works. First, we create a basic “arrayProcessor” class, which provides a common interface to perform regular array operations, instead of using the native PHP functions. Here is its definition:

class arrayProcessor{

var $data;

function arrayProcessor($data=array()){

(is_array($data))?$this->data=$data:die(‘Invalid parameter ‘.$data);

}

function getFirstElement(){

return reset($this->data);

}

function getCurrentElement(){

return current($this->data);

}

function getLastElement(){

return end($this->data);

}

function getPreviousElement(){

return prev($this->data);

}

function getNextElement(){

return next($this->data);

}

function reverseElements($prekeys=true){

return array_reverse($this->data,$prekeys);

}

function sortElements(){

sort($this->data);

return $this->data;

}

function getRange($offset,$length){

return array_slice($this->data,$offset,$length);

}

function getRandomElement(){

shuffle($this->data);

return $this->data[0];

}

function searchElement($keyword){

return array_search($keyword,$this->data);

}

function countElements(){

return count($this->data);

}

}

As you can see, our “arrayProcessor” class presents several clever methods for manipulating arrays for different purposes, and accepts only one parameter, $data, which is assigned a default array value. Also, I’ve defined the most common array operations (of course you can add your own), so each method is designed specifically to handle array elements in some manner. By simply instantiating an “arrayProcessor” object and utilizing its methods, we’re able to move back and forward within the structure, reverse, sort and extract elements, and so forth.

If we take a moment and analyze the above defined class, it seems like we’re implementing an already existing PHP functionality. Why go to the trouble of designing such a class, when we can directly use the native array functions? The truth is that we’re providing a single interface to access array elements, focusing mainly on the handled data and hiding any internal processing from outside. That’s what makes objects behave as “black boxes,” and naturally “pluggable” block elements.

Okay, we were talking about object aggregation, right? So, we need to define the other sample class, to see in detail how both classes can work together. Therefore, the next step consists of defining the second class, which simply takes care of sending by email a hypothetical newsletter to several possible recipients. This newly created class, named “dataMailer” is defined as follows:

class dataMailer {

var $arrayProc;

var $subject;

var $message;

var $headers;

function dataMailer(&$arrayProc){

$this->arrayProc=&$arrayProc;

$this->subject=’Object-Oriented PHP NewsLetter';

$this->message=’Hi, this is the ultimate Object-Oriented PHP newsletter!';

$this->headers=’MIME-Version: 1.0′.”rn”.’Content-type: text/html; charset=iso-8859-1′.”rn”;

}

function setSubject($subject){

$this->subject=$subject;

}

function setMessage($message){

$this->message=$message;

}

function setHeaders($headers){

$this->headers=$headers;

}

function sendData($firstRecip,$numberRecip){

$recipients=&$this->arrayProc->getRange($firstRecip,$numberRecip);

foreach($recipients as $recipient){

if(!mail($recipient,$this->subject,$this->message,$this->headers)){

die(‘Failed to send mail to recipient :’.$recipient);

}

}

}

}

Because of its simplicity, the class is really easy to understand. But, let’s take a detailed look at what it does, so that implementing its usage will be even clearer.

The class displays several data members that will be explained in turn. However, let’s stop for a while at the first member, $arrayProc, because it’s the key element for making this second class work. In this case, $arrayProc composes an instance of the “arrayProcessor” class, which is passed as the unique parameter to the constructor and assigned as a class property. Doing so, the “dataMailer” class is able to use all of the functional methods present in the first class. 

This condition is better illustrated below, listing the class constructor:

function dataMailer(&$arrayProc){

$this->arrayProc=&$arrayProc;

$this->subject=’Object-Oriented PHP NewsLetter';

$this->message=’Hi, this is the ultimate Object-Oriented PHP newsletter!';

$this->headers=’MIME-Version: 1.0′.”rn”.’Content-type: text/html; charset=iso-8859-1′.”rn”;

}

In this situation, “dataMailer” aggregates the “arrayProcessor” object, clearly showing aggregation’s real power, since within the second class, we’re accessing the methods provided by “arrayProcessor.”

One point worth considering is that we’re passing a reference of the instance of the first class (notice the usage of the & ampersand operator, preceding the object), something commonly used in this type of interaction.

Now, can you see the implicit possibilities that this object aggregation process offers to us? With such a powerful interaction, certainly we’re able to implement a few classes, make them interact in this way, and build up well-defined structures for Web applications.

Once we’ve explained how an object aggregates another object, let’s go back to the “dataMailer” class, to define the rest of the class data members. First we define the $subject property, that means the subject of the email message to be sent. Next, we have $message, which defines the body of the message, and finally $headers that, as the name clearly suggests, composes the MIME headers to be send along with the message. Simple and straightforward, yes?

However, we’re just beginning to see the power of aggregation. Let’s go deeper in the structure of our “dataMailer” class to see how it uses the functionality of “arrayProcessor.” Keep reading.

{mospagebreak title=A closer look at aggregation: the boosted “dataMailer” class}

As we’ve seen previously, our “dataMailer” class establishes a well-defined object interaction by accepting one instance of “arrayProcesssor.” Besides displaying the corresponding modifiers for $subject, $message and $headers, the class presents another method: “sendData(),” which is the real workhorse of the class. This method simply obtains the email addresses of each recipient from an array structure (more about this in a moment), builds up the structure of the message, adds the proper subject and the message headers, and finally sends the newsletter to the given email addresses.

Here’s where things get really exciting. Notice that this method accepts two parameters: $firstRecip and $numberRecips, respectively. Since we’re obtaining email addresses from an array, the first argument represents the initial offset within the array, and the second means the numbers of email addresses extracted from it. But, how do we obtain this data? Well, if we have a look at the class code, we can see the following line:

$recipients=&$this->arrayProc->getRange($firstRecip,$numberRecip);

As you can see, here we’re using the “getRange()” method of the “arrayProcessor” class to retrieve a range of email addresses for sending the newsletter. In other words, we’re taking advantage of the functionality that is generously offered by the “arrayProcessor” class, utilizing one of its methods for the specific purposes of the “dataMailer” class. Now, are you starting to see the great benefits of aggregation? I hope so!

The rest of the method is easy to follow. It simply iterates over the email addresses array and send the messages to the given recipients, like this:

foreach($recipients as $recipient){

if(!mail($recipient,$this->subject,$this->message,$this->headers)){

die(‘Failed to send email to recipient :’.$recipient);

}

}

Definitely, through the usage of the first object within the environment of the second, we’ve boosted its functionality. Since the structure of the “dataMailer” class is easily expandable, we might want to change the “sendData()” method to send a message to a randomly chosen recipient. The newly rewritten method would look something like this:

function sendData(){

$recipient=&$this->arrayProc->getRandomElement();

if(!mail($recipient,$this->subject,$this->message,$this->headers)){

die(‘Failed to send mail to recipient :’.$recipient);

}

}

Wasn’t that easy? This time we’re using the “getRandomElement()” provided by our “arrayProcessor” object to randomly select a lucky recipient for newsletter. As you can see, there are many possible ways to exploit the awesome capabilities of aggregation in PHP. It’s just a matter of putting a couple of classes to work and making them interact. It’s really fun.

However, so far we’ve specifically focused our attention on the source code for our two brand new classes. It’s time to show a concrete example to demonstrate the benefits of aggregation. So, let’s jump right into the sample code.

{mospagebreak title=Aggregation in action: a concrete example}

Armed with the above defined classes, we’ll demonstrate with a basic yet illustrative example how to implement aggregation. First, let’s define a simple text file that stores the email addresses corresponding to our newsletter’s subscribers. The “subscribers.dat” file would look as simple as follows:

john@crazyprotocols.com

hellen@crazyprotocols.com

nancy@randomports.com

daniel@randomports.com

susan@bynarygifts.com

rachel@bynarygifts.com

It looks like we’re not attracting many subscribers, but for the purposes of our example, this works. Okay, having defined our data file, let’s email our visitors the newsletter:

// include the classes

require_once ‘arrayprocessorclass.php';

require_once ‘datamailerclass.php';

// read subscriber email addresses

$data=file(‘subscribers.dat’);

// instantiate a new arrayProcessor object

$ap=&new arrayProcessor($data);

// instantiate a new dataMailer object and aggregate arrayProcessor object to dataMailer object

$dm=&new dataMailer($ap);

// send data to subscribers

$dm->sendData(0,6);

With these few lines of code, we’re sending our newsletter. Although the code is clear enough, let’s explain its logic. As usual, we include the proper class files for object instantiation. Then, we read the email addresses from the text file previously created, storing them in the $data array:

$data=file(‘subscribers.dat’);

The next task consists of instantiating the objects and perform the aggregation process, passing the “arrayProccessor” object to the constructor of “dataMailer,” as indicated below:

// instantiate a new arrayProcessor object

$ap=&new arrayProcessor($data);

// instantiate a new dataMailer object and aggregate arrayProcessor object to dataMailer object

$dm=&new dataMailer($ap);

Lastly, we email the newsletter by using the “sendData()” method, specifying the starting point within the $data array, and the number of elements to be processed. In this case, we’ve decided to process all of the email addresses, passing the values 0 and 6 to the method, as follows:

$dm->sendData(0,6);

If we ever wanted to send data to only the first three subscribers, the following expression should be used:

$dm->sendData(0,3);

Despite the example’s simplicity, it shows how easily object aggregation can be implemented. However, these are a just a few ideas to get you started. I’m pretty sure you can think up some more interesting examples to “aggregate” this functionality in your next project.

Conclusion

At this point, we have been exploring the arena of object interaction, digging into the concept of aggregation, as well as its possible uses in different scenarios. While the examples shown present a clear, easy-to-follow logic, they are fairly good to get you started on the subject with only minor hassles.

But, don’t feel as if this is the end of the story. There are still more items to be reviewed. In the next part of this series, we’ll implement aggregation in a rather more complex condition, to solve some frequent problems that most developers face on a regular basis, such as building up a paging class that aggregates a MySQL abstraction class. In the meantime, feel free to use the given classes and make them interact!

[gp-comments width="770" linklove="off" ]

chat sex hikayeleri Ensest hikaye