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