Categories
PHP

Object Cloning in PHP

Object cloning is the act of making a copy of an object. Cloning in PHP is done by making a shallow copy of the object. This means that internal objects of the cloned object will not be cloned, unless you explicitly instruct the object to clone these internal objects too, by defining the magic method __clone().

In simple words,

Cloning is used to create a genuine copy of an object. Assigning an object to another variable does not create a copy – rather, it creates a reference to the same memory location as the object:

$o = new stdclass;
$o->a = 'b';
$o->b = 'c';

$o2 = $o;
$o2->a = 'd';

var_dump($o);
var_dump($o2);

$o3 = clone $o;
$o3->a = 'e';
var_dump($o);
var_dump($o3);

This example code will output the following:

object(stdClass)#1 (2) {
  ["a"]=>
  string(1) "d"
  ["b"]=>
  string(1) "c"
}
object(stdClass)#1 (2) {
  ["a"]=>
  string(1) "d"
  ["b"]=>
  string(1) "c"
}
object(stdClass)#1 (2) {
  ["a"]=>
  string(1) "d"
  ["b"]=>
  string(1) "c"
}
object(stdClass)#2 (2) {
  ["a"]=>
  string(1) "e"
  ["b"]=>
  string(1) "c"
}

If you don’t utilize the __clone method, the internal objects of the new object will be references to the same objects in memory as the internal objects of the original object that was cloned.

// in this example the internal member $_internalObject of both objects
// reference the same instance of stdClass in memory.
class CloneableClass
{
    private $_internalObject;

    public function __construct()
    {
        // instantiate the internal member
        $this->_internalObject = new stdClass();
    }
}

$classA = new CloneableClass();
$classB = clone $classA;

// in this exampe the internal member $_internalObject of both objects
// DON'T reference the same instance of stdClass in memory, but are inividual instances
class CloneableClass
{
    private $_internalObject;

    public function __construct()
    {
        // instantiate the internal member
        $this->_internalObject = new stdClass();
    }

    // on clone, make a deep copy of this object by cloning internal member;
    public function __clone()
    {
        $this->_internalObject = clone $this->_internalObject;
    }
}

$classA = new CloneableClass();
$classB = clone $classA;

Use cases for cloning would for instance be a case where you don’t want outside objects to mess with the internal state of an object.

Let’s say you have a class User with a internal object Address.

class Address
{
    private $_street;
    private $_streetIndex;
    private $_city;
    // etc...

    public function __construct( $street, $streetIndex, $city /* etc.. */ )
    {
        /* assign to internal values */
    }
}

class User
{
    // will hold instance of Address
    private $_address;

    public function __construct()
    {
        $this->_address = new Address( 'somestreet', '1', 'somecity' /* etc */ );
    }

    public function getAddress()
    {
        return clone $this->_address;
    }
}

For arguments sake, let’s say you don’t want outside objects to mess with the internal Address of User objects, but you do want to be able to give them a copy of the Address object. The above example illustrates this. The getAddress method returns a clone of the address object to calling objects. This means that if the calling object alters the Address object, the internal Address of User will not change. If you didn’t give a clone, then the outside object would be able to alter the internal Address of User, because a reference is given by default, not a clone.

An object copy is created by using the clone keyword (which calls the object’s __clone() method if possible).  An object’s __clone() method cannot be called directly.

$copy_of_object = clone $object;

Creating a copy of an object with fully replicated properties is not always the wanted behavior. If your object holds a reference to another object which it uses and when you replicate the parent object you want to create a new instance of this other object so that the replica has its own separate copy.

class SubObject
{
    static $instances = 0;
    public $instance;

    public function __construct() {
        $this->instance = ++self::$instances;
        echo "SubObject construct\n";
    }

    public function __clone() {
        $this->instance = ++self::$instances;
        echo "SubObject clone\n";
    }
}

class MyCloneable
{
    public $object1;
    public $object2;

    function __clone()
    {
        // Force a copy of this->object, otherwise
        // it will point to same object.
        $this->object1 = clone $this->object1;
        echo "MyCloneable clone\n\n";
    }
}

$obj = new MyCloneable();
echo "new MyCloneable() -- Done with MyCloneable \n\n";

echo "calling new SubObject() \n";
$obj->object1 = new SubObject();
echo "new SubObject() -- Done with SubObject1 \n";
echo "calling new SubObject() \n";
$obj->object2 = new SubObject();
echo "new SubObject() -- Done with SubObject2 \n\n";

echo "calling clone of MyCloneable object \n";
$obj2 = clone $obj;

print("Original Object:\n");
print_r($obj);

print("Cloned Object:\n");
print_r($obj2);

resulting to

new MyCloneable() -- Done with MyCloneable

calling new SubObject()
SubObject construct
new SubObject() -- Done with SubObject1
calling new SubObject()
SubObject construct
new SubObject() -- Done with SubObject2

calling clone of MyCloneable object
SubObject clone
MyCloneable clone

Original Object:
MyCloneable Object
(
    [object1] => SubObject Object
        (
            [instance] => 1
        )

    [object2] => SubObject Object
        (
            [instance] => 2
        )
)

Cloned Object:
MyCloneable Object
(
    [object1] => SubObject Object
        (
            [instance] => 3
        )

    [object2] => SubObject Object
        (
            [instance] => 2
        )
)
'Coz sharing is caring
Categories
PHP

OOP vs Procedural Code

After being the part of long discussion this evening, I felt that I should write a post about the real differences between OOP and Procedural coding styles. Hint: whether you use classes and objects or not has very little to do with the answer…

Procedural Programming

Wikipedia defines procedural programming as:

Procedural programming can sometimes be used as a synonym for imperative programming (specifying the steps the program must take to reach the desired state), but can also refer (as in this article) to a programming paradigm, derived from structured programming, based upon the concept of the procedure call.

That’s a decent definition, but let’s see if we can improve upon it. I’m going to assert here that procedural programming is really just the act of specifying a set of ordered steps needed to implement the requested functionality. How those steps are implemented is a detail that’s not related to the paradigm. The important thing is that it’s imperative in how it works. Let’s look at a few examples:

Obviously procedural:

$m = mysqli_connect(...);
$res = mysqli_query($m, $query);
$results = array();
while ($row = mysqli_fetch_assoc($res)) {
    $results[] = $row;
}

This is also procedural, even though it uses an object:

$m = new MySQLi(...);
$res = $m->query($query);
$results = array();
while ($row = $m->fetch_assoc($res)) {
    $results[] = $row;
}

This is still procedural, even though it uses a class:

class GetResults {
    public function getResults() {
        $m = new MySQLi(...);
        $res = $m->query($query);
        $results = array();
        while ($row = $m->fetch_assoc($res)) {
            $results[] = $row;
        }
        return $results;
    }
}

Note that all three of those examples use the exact same code structure. The only difference between them is the way the routines are resolved. But each is procedural. Each has discrete steps that must be taken. Let’s look at what OOP is and why this is different…

Object Oriented Programming

Wikipedia defines object oriented programming as:

Object-oriented programming (OOP) is a programming paradigm using “objects” – data structures consisting of data fields and methods together with their interactions – to design applications and computer programs. Programming techniques may include features such as data abstractionencapsulationmessagingmodularitypolymorphism, and inheritance.

Again, that’s a decent definition. But I only agree with the second part. The first sentence says that you must use object data structures to write OOP. That’s blatantly wrong. You can completely implement data abstraction, encapsulation, messaging, modularity, polymorphism and (to a limited extent) inheritance without using an object structure. What I’d argue makes code OOP is a few things. First, it must abstract the data concepts into modular units. Second, it must have some way to polymorphically execute code. Finally, it must at least partially encapsulate that code and functionality. Let’s look at a few examples before continuing further:

A classic OOP pattern:

class Mediator {
    protected $events = array();
    public function attach($eventName, $callback) {
        if (!isset($this->events[$eventName])) {
            $this->events[$eventName] = array();
        }
        $this->events[$eventName][] = $callback;
    }
    public function trigger($eventName, $data = null) {
        foreach ($this->events[$eventName] as $callback) {
            $callback($eventName, $data);
        }
    }
}
$mediator = new Mediator;
$mediator->attach('load', function() { echo "Loading"; });
$mediator->attach('stop', function() { echo "Stopping"; });
$mediator->attach('stop', function() { echo "Stopped"; });
$mediator->trigger('load'); // prints "Loading"
$mediator->trigger('stop'); // prints "StoppingStopped"

The same pattern, using functions.

$hooks = array();
function hook_register($eventName, $callback) {
    if (!isset($GLOBALS['hooks'][$eventName])) {
        $GLOBALS['hooks'][$eventName] = array();
    }
    $GLOBALS['hooks'][$eventName][] = $callback;
}
function hook_trigger($eventName, $data = null) {
    foreach ($GLOBALS['hooks'][$eventName] as $callback) {
        $callback($eventName, $data);
    }
}

As you can see, both follow the Mediator Pattern. Both are object oriented, because they both are designed to de-couple caller from sender. Both provide state, and are modular. The difference here, is that one is implemented using a traditional object (and is hence reusable, a very good advantage) and the other is not reusable since it depends on a global variable. I used the term “hook” here for a very important reason. It’s the name of the event system that Drupal uses.

Drupal in a lot of ways is very object oriented. Their module system, their hook system, their form system, etc are all object oriented. But none of them use objects for that. They use functions and dynamic dispatch. This leads to some really awkward tradeoffs, so I’m not suggesting that it’s a good thing, just that it’s a proof that you don’t need classes to write OOP.

Why does it matter?

It matters for a very simple reason. A lot of developers think that just because they use classes, they are writing OOP. And others think that because they use functions, they are using procedural programming. And that’s not true. Procedural vs OOP is an approach to writing code, not how you write it. Are you focusing on “Steps” and an ordered way of writing a program? You’re likely writing procedural code. But if you’re focusing on state transformations and encapsulated abstractions, you’re writing OOP.

Classes are just a tool that make writing real OOP easier. They aren’t a requirement or a indicator that you’re writing OOP.

Just My $0.02…

Update: OOP Database Access

So, some of you are asking what database access would look like in OOP code. The reason that I didn’t include an example is that it’s all abstracted away. In reality, the way that I would do that query could be:

$mapper = new PersonDataMapper(new MySQLi(...));
$people = $mapper->getAll();

Where $people is an array of person objects. Note that it’s a responsibility that’s abstracted away. So in your business objects you’d never access the database directly. You’d use a mapper to translate back and forth from your business objects to the data store. Internally, a specific mapper will build a query, execute it, and fetch results, but that’s all abstracted away. We can change the implementation detail of the database layer by simply swapping out a mapper.

The responsibility of data persistence becomes an encapsulated abstraction. And that’s why it’s not procedural but object oriented…

'Coz sharing is caring