[2 days left] What’s wrong with your cloud strategy? Learn why multicloud solutions matter with Nimble Storage.Register Now

x
?
Solved

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

Posted on 2014-04-08
12
Medium Priority
?
209 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 5
  • 2
12 Comments
 
LVL 111

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 111

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
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
LVL 35

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 35

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 35

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 35

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 35

Accepted Solution

by:
Dan Craciun earned 2000 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

Important Lessons on Recovering from Petya

In their most recent webinar, Skyport Systems explores ways to isolate and protect critical databases to keep the core of your company safe from harm.

Question has a verified solution.

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

Developers of all skill levels should learn to use current best practices when developing websites. However many developers, new and old, fall into the trap of using deprecated features because this is what so many tutorials and books tell them to u…
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.
The viewer will learn how to count occurrences of each item in an array.
The viewer will learn how to create and use a small PHP class to apply a watermark to an image. This video shows the viewer the setup for the PHP watermark as well as important coding language. Continue to Part 2 to learn the core code used in creat…

649 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