Chaining Multiple Objects in PHP
I like encapsulation. Unfortunately PHP is a language that presents some interesting challenges to the classical interpretation of Object Oriented Programming.
There’s a couple things you should know about objects in PHP:
- Objects became available in PHP in version 5. We’re still on version 5 today, even though it came out in 2004… *rolls eyes*
- At this time, PHP Doesn’t support multiple inheritance. This means you can only chain objects together one by one.
- Object oriented php is a little slower than procedural php, as discussed here
- Constructors are only called on the implemented object.
The last one is a little important. If you instantiate an object, only that object’s constructor will be called by PHP. This is important when you start extending other objects that also have constructors. You’ll have errors unless you manually call the constructor of each parent with
parent::__construct();
Is it Worth It?
Some would say, no, just chuck every function that’s needed for this sort of thing into one big object. Personally, I like encapsulation. At the least, it makes functions easier to read. At the best, it keeps everything clean and organized and functioning properly while allowing reverse compatibility during future changes.
After building a few objects and changing them by simply using the extends keyword, I wanted to know if all that work I just did to encapsulate 5 different objects was actually going to be run slower by PHP than if I had left it as one big blob.
The Code
$iterations = 10000;
//--------------------------------------------------
$start = microtime(true);
class test{
public $apples;
public $oranges;
public $pares;
public function apples(){
$this->apples++;
}
public function oranges(){
$this->oranges++;
}
public function pares(){
$this->pares++;
}
}
$test = new test;
for($x=0; $x<$iterations; $x++){ $test->apples();
$test->oranges();
$test->pares();
}
$end = microtime(true) - $start;
$output .= '<hr/>Single Object Elapsed: ' . $end;
//--------------------------------------------------
//--------------------------------------------------
$start = microtime(true);
class apple{
public $apples;
public function apples(){
$this->apples++;
}
}
class orange extends apple{
public $oranges;
public function oranges(){
$this->oranges++;
}
}
class pare extends orange{
public $pares;
public function pares(){
$this->pares++;
}
}
class test2 extends pare{
}
$test2 = new test2;
for($x=0; $x<$iterations; $x++){ $test2->apples();
$test2->oranges();
$test2->pares();
}
$end = microtime(true) - $start;
$output .= '<hr/>Multiple Objects Elapsed: ' . $end;
//--------------------------------------------------
The Results
| | | |
. | | single object | multiple objects |
. | average | 0.028138… | 0.028823… |
. | Trial 1 | 0.0195 | 0.0314 |
. | 2 | 0.0212 | 0.0331 |
. | 3 | 0.0281 | 0.011 |
. | 4 | 0.0113 | 0.0557 |
. | 5 | 0.0213 | 0.0312 |
. | 6 | 0.0213 | 0.0312 |
. | 7 | 0.0213 | 0.0476 |
. | 8 | 0.0112 | 0.0115 |
. | 9 | 0.0413 | 0.0113 |
. | 10 | 0.0535 | 0.0334 |
. | 11 | 0.0113 | 0.0113 |
. | 12 | 0.0433 | 0.0109 |
. | 13 | 0.0112 | 0.0113 |
. | 14 | 0.0112 | 0.0112 |
. | 15 | 0.0313 | 0.0338 |
. | 16 | 0.0213 | 0.0314 |
. | 17 | 0.0275 | 0.0312 |
. | 18 | 0.0112 | 0.0112 |
. | 19 | 0.0211 | 0.0331 |
. | 20 | 0.022 | 0.0604 |
. | 21 | 0.0211 | 0.033 |
. | 22 | 0.0414 | 0.0312 |
. | 23 | 0.0456 | 0.0365 |
. | 24 | 0.0698 | 0.0546 |
. | 25 | 0.0372 | 0.0294 |
. | 26 | 0.0551 | 0.0215 |
Conclusion
Now I’m just more confused than when I started. On average, it looks like chaining objects together is marginally slower than just lumping all the functions together in one object. Although the fringe cases prove that sometimes it is much faster… and yet, sometimes much slower.
Looks like a wash to me.