ID:               30787
 Comment by:       ericvanblokland at gmail dot com
 Reported By:      php dot net at nanonanonano dot net
 Status:           Assigned
 Bug Type:         Scripting Engine problem
 Operating System: Debian Sarge
 PHP Version:      4.3.9
 Assigned To:      andi
 New Comment:

I think this report is a duplicate of 24485
http://bugs.php.net/bug.php?id=24485


Previous Comments:
------------------------------------------------------------------------

[2004-11-27 14:53:41] [EMAIL PROTECTED]

It seems to me, that some magic with refernces is causing this
problem.
Here is simplified reproduce code:
<?
class B {
  var $b="original value\n";
  function echoB() { echo $this->b; }
}

class A {
  var $a;
  function A() { $this->a = new B(); }
}

$c = new A();
$c->a->echoB(); //comment this
var_dump($c);
$e = $c;
$e->a->b="a new copy\n";
var_dump($c);
?>
Comment marked line to see expected result.

------------------------------------------------------------------------

[2004-11-15 00:36:21] php dot net at nanonanonano dot net

Description:
------------
If I instantiate an object using 'new' and then copy it, I get a true
copy of the object.

If I then use a method within that object, the next time I copy it, I
only get a reference not an object. 

This behaviour is inconsistent (the behaviour of the = operator depends
on whether a method has been called or not) and annoying (it prevents
creating a prototype object by customising it after it has been
instantiated and then replicating it as needed).

I have read in other similar bug reports that "it's not a bug, it's a
feature", but that response misses three important points:

* it reduces functionality (cannot replicate a proto-object)

* the behaviour is inconsistent and the programmer has no way of
knowing whether the = operator will perform a copy by value or a copy
by reference on member-objects within an object without doing a lot of
code auditing (and one small change elsewhere in the code, might have
significant side-effects)

* It is not documented *anywhere* in the php manual. I know... I've
just wasted my entire weekend trying to find some way of working around
this problem.

Please don't just blow me off on this one as "NOTABUG", please think
about the functionality that is supposed to be here for the poor shmuck
programmer! While I personally believe this is a bug in the way PHP
handles objects (cf. any other OO-language), it is at the very least a
bug against the documentation.


-----------
For those googling on this problem, the example code has one workaround
(no doubt there are others) for a 'safe' way of touching member
variables that are objects so that they do not get stuffed up and
magically convert to references. For non-const methods, one can copy
the member, run whatever methods are required on the copy, and then
copy it back over the member-object:

function safeAlter($newValue) {
  //another horrible hack: why can't we just do
  //$this->alterB($newvalue);
  $acopy = $this->a;
  $acopy->alterB($newValue);
  $this->a = $acopy;
}

Or you can use serialize() and unserialize() to copy objects to make
sure they are copied by value without any magic references appearing
(horrible and liable to break many other things, but it will probably
work...).

Reproduce code:
---------------
class BB {
  var $b="original value\n";
  function BB() {}
  function echoB() { echo $this->b; }
}

class AA {
  var $a;
  function AA() { $this->a = new BB(); }
  function unsafeEcho() { $this->a->echoB(); }
  function safeEcho() {
    $acopy = $this->a;
    $acopy->echoB();
  }
}

$protoA = new AA();
$a2 = $protoA;
$protoA->unsafeEcho();
$a3 = $protoA;
$a3->a->b="a new copy\n";
echo $protoA->a->b;

Expected result:
----------------
Objects $a2 and $protoA are completely independent objects as  $a2 has
been created the by copy-by-value assignment operator (=).

Objects $a3 and $protoA should also be different as the code to create
$a3 from $protoA is the same as for $a2.

Changing $a2 should not alter $protoA as $a2 was created from  $protoA
by copy-by-value assignment. Similarly, changing $a3 should not alter
$protoA.

Expected output:
---8<---
original value
original value


Actual result:
--------------
Objects $a2 and $protoA are completely independent objects as  $a2 has
been created the by copy-by-value assignment operator (=).

Objects $a3 and $protoA are *not* different even though the code to
create $a3 is the same.... one of the members of $protoA has
mysteriously changed itself into a reference from a value!?

Changing $a2 does not alter $protoA as expected.

Changing $a3 mysteriously alters $protoA as one of the members of
$protoA has mysteriously changed itself into a reference from a
value!?

Actual output:
---8<---
original value
a new copy



------------------------------------------------------------------------


-- 
Edit this bug report at http://bugs.php.net/?id=30787&edit=1

Reply via email to