Solved

I do not understand how a cloned object can edit the original object

Posted on 2014-04-08
12
200 Views
Last Modified: 2014-04-16
<?php
class Account {
    public $balance;
    function __construct( $balance ) {
        $this->balance = $balance;
    }
    function display(){
      return $this->balance;
    }
}

class Person {
    private $name;
    private $age;
    private $id;
    public $account;

    function __construct( $name, $age, Account $account ) {
        $this->name = $name;
        $this->age  = $age;
        $this->account = $account;
    }

    function setId( $id ) {
        $this->id = $id;
    }

    function __clone() {
        $this->id   = 0;
    }
}

$person = new Person( "bob", 44, new Account( 200 ) );
$person->setId( 343 );
$person2 = clone $person;

// give $person some money
$person->account->balance += 10;
// $person2 sees the credit too
print $person2->account->balance;
echo '<br>person2: display: '.$person2->account->display();

// output:
// 210

echo '<br>';
// give $person2 some money
$person2->account->balance += 10;
// $person sees the credit too
print $person->account->balance;
echo '<br>person: display: '.$person->account->display();

?>

Open in new window


I understood the code with cloning

So I decided to add
// give $person2 some money
$person2->account->balance += 10;
// $person sees the credit too
print $person->account->balance;
echo '<br>person: display: '.$person->account->display();

but now I do not understand how a cloned object can edit the original object


this is the output:
210
person2: display: 210
220
person: display: 220
0
Comment
Question by:rgb192
  • 5
  • 5
  • 2
12 Comments
 
LVL 108

Expert Comment

by:Ray Paseur
ID: 39987671
Are you suspicious of this?

   function __clone() {
        $this->id   = 0;
    }
This is one of those things that needs some attention to var_dump() so you can see the data.
0
 

Author Comment

by:rgb192
ID: 39987787
<?php
class Account {
    public $balance;
    function __construct( $balance ) {
        $this->balance = $balance;
    }
    function display(){
      return $this->balance;
    }
}

class Person {
    private $name;
    private $age;
    private $id;
    public $account;

    function __construct( $name, $age, Account $account ) {
        $this->name = $name;
        $this->age  = $age;
        $this->account = $account;
    }

    function setId( $id ) {
        $this->id = $id;
    }

    function __clone() {
        $this->id   = 0;
    }
}

$person = new Person( "bob", 44, new Account( 200 ) );
$person->setId( 343 );
$person2 = clone $person;

// give $person some money
$person->account->balance += 10;
// $person2 sees the credit too
print $person2->account->balance;
echo '<br>person2: display: '.$person2->account->display();

// output:
// 210

echo '<br><pre>';
var_dump($person);
var_dump($person2);
echo '</pre>';

echo '<br>';
// give $person2 some money
$person2->account->balance += 10;
// $person sees the credit too
print $person->account->balance;
echo '<br>person: display: '.$person->account->display();

echo '<br><pre>';
var_dump($person);
var_dump($person2);
echo '</pre>';

?>

Open in new window


210
person2: display: 210

object(Person)#1 (4) {
  ["name":"Person":private]=>
  string(3) "bob"
  ["age":"Person":private]=>
  int(44)
  ["id":"Person":private]=>
  int(343)
  ["account"]=>
  object(Account)#2 (1) {
    ["balance"]=>
    int(210)
  }
}
object(Person)#3 (4) {
  ["name":"Person":private]=>
  string(3) "bob"
  ["age":"Person":private]=>
  int(44)
  ["id":"Person":private]=>
  int(0)
  ["account"]=>
  object(Account)#2 (1) {
    ["balance"]=>
    int(210)
  }
}


220
person: display: 220

object(Person)#1 (4) {
  ["name":"Person":private]=>
  string(3) "bob"
  ["age":"Person":private]=>
  int(44)
  ["id":"Person":private]=>
  int(343)
  ["account"]=>
  object(Account)#2 (1) {
    ["balance"]=>
    int(220)
  }
}
object(Person)#3 (4) {
  ["name":"Person":private]=>
  string(3) "bob"
  ["age":"Person":private]=>
  int(44)
  ["id":"Person":private]=>
  int(0)
  ["account"]=>
  object(Account)#2 (1) {
    ["balance"]=>
    int(220)
  }
}

Open in new window



I notice in var_dump
$person is listed every time
and there is no $person2

is this because $person2 was formed using a clone
0
 
LVL 108

Expert Comment

by:Ray Paseur
ID: 39988294
Sorry - I'll be out of town for a few days.  Hopefully one of the other Experts will pick this up.  Taxi is waiting now.  Good luck!
0
 
LVL 34

Expert Comment

by:Dan Craciun
ID: 39991274
In the var_dump you only see the class, and that is Person.

In php, clone creates a shallow copy, which means the cloned object's properties that are objects point to the properties of the original object.

Effectively clone by default does not clone included objects also.

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 (it clones the reference).

If you want to change that, you use the __clone() method. Php calls that method after the clone is complete, so any properties you want to make unique to the clone have to be initialized in the __clone method.

HTH,
Dan
0
 
LVL 34

Expert Comment

by:Dan Craciun
ID: 39995184
OK, try no 2 :)

You've read about passing parameters by value and by reference, so the concepts should be clear.

In PHP, after you do $x = 1; $x will have the value 1.
If you do $obj = new Account(); $obj will be a reference to an instance of the class Account, or, in other words, $obj's value is a reference to Account.

When you use clone, PHP will create a new object and copy all the values of the cloned instance variables.

In your example, $person contains:
$name with the value: 'bob'
$age with the value: 44
$id with the value: 343
$account with the value: a reference to an instance of the class Account

After you use clone, PHP will create a new object ($person2) with brand new variables and give them the original's object values:
$name with the value: 'bob'
$age with the value: 44
$id with the value: 343
$account with the value: a reference to the same instance of the class Account
After finishing the copy, PHP will run __clone() and set $id to 0.

Looking at the above, you can see that after clone,
$person->account and $person2->account both have equal values, which means they both point to the same object.

If you want to avoid that, modify __clone() like this:
function __clone() {
        $this->id   = 0;
        $this->account = new Account(0)
    }

This will create a new instance of the Account class, and $person2->account will point to that new instance.

Please tell me if I wasn't clear enough.
0
 

Author Comment

by:rgb192
ID: 39996305
Ok. In current output what is (person) #1 (4) and (person) #3 (4)
0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 34

Expert Comment

by:Dan Craciun
ID: 39996330
Those are instances no 1 and respectively no 3 of the class Person and each one has 4 properties/class variables.
0
 

Author Comment

by:rgb192
ID: 39996353
I did var_dump 1,2
Output is #1,3
0
 
LVL 34

Expert Comment

by:Dan Craciun
ID: 39996373
Yes, because the instances are numbered sequentially for all classes, not for each class.
So in your case:
#1: the first instance of class Person
#2: the first instance of class Account
#3: the second instance of class Person
0
 

Author Comment

by:rgb192
ID: 39997963
#1: the first instance of class Person
#2: the first instance of class Account
#3: the second instance of class Person

what about $person2
is $person2 an instance of class person
0
 
LVL 34

Accepted Solution

by:
Dan Craciun earned 500 total points
ID: 39998189
Of course. If $person is an instance of the class Person, then it's clone will be a new instance of the same class.
0
 

Author Closing Comment

by:rgb192
ID: 40004793
so clone is copy in var_dump
thanks
0

Featured Post

What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

Join & Write a Comment

Introduction HTML checkboxes provide the perfect way for a web developer to receive client input when the client's options might be none, one or many.  But the PHP code for processing the checkboxes can be confusing at first.  What if a checkbox is…
This article discusses how to create an extensible mechanism for linked drop downs.
The viewer will learn how to look for a specific file type in a local or remote server directory using PHP.
This tutorial will teach you the core code needed to finalize the addition of a watermark to your image. The viewer will use a small PHP class to learn and create a watermark.

746 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now