Solved

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

Posted on 2014-04-08
12
202 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 109

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 109

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
Courses: Start Training Online With Pros, Today

Brush up on the basics or master the advanced techniques required to earn essential industry certifications, with Courses. Enroll in a course and start learning today. Training topics range from Android App Dev to the Xen Virtualization Platform.

 
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
 
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

Gigs: Get Your Project Delivered by an Expert

Select from freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely and get projects done right.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Since pre-biblical times, humans have sought ways to keep secrets, and share the secrets selectively.  This article explores the ways PHP can be used to hide and encrypt information.
Introduction This article is intended for those who are new to PHP error handling (https://www.experts-exchange.com/articles/11769/And-by-the-way-I-am-New-to-PHP.html).  It addresses one of the most common problems that plague beginning PHP develop…
The viewer will learn how to look for a specific file type in a local or remote server directory using PHP.
The viewer will learn how to create a basic form using some HTML5 and PHP for later processing. Set up your basic HTML file. Open your form tag and set the method and action attributes.: (CODE) Set up your first few inputs one for the name and …

806 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