Re: Weird behaviour with references to objects...
| From: | Marco Tabini | Date: | Fri, 08 Nov 2002 03:19:54 +0000 |
| Subject: | Re: Weird behaviour with references to objects... | ||
| References: | 1 | Groups: | php.general |
| Request: | Send a blank email to php-general+get-123302@lists.php.net to get a copy of this message | ||
I'm not sure if my answer is going to be of much help, but I think this
has to do with the way PHP handles references and copies of objects--it
uses what I understand is a lazy copy mechanism, and thus the results on
object manipulations can yield odd results. There was a discussion on a
similar problem on PHP-DEV a while back--if you search the forums you
should be able to find it.
Hope this helps...
Marco
-------------
php|architect -- The Monthly Magazine For PHP Professionals
Come visit us on the web at http://www.phparch.com!
On Thu, 2002-11-07 at 21:36, Tim Molendijk wrote:
> First of all I would like to say that I know this is a lot of text but I
> would be very pleased if you take a little time to read it nevertheless. The
> situation described below is not complicated at all...
> =====================================
>
> Hello all,
>
> I'm dealing with this really weird problem which occurs when dealing with
> references within objects pointing to other objects. I'm trying to find out
> what it is now for a few days and I still don't get it. I minimised the code
> around the problem and it's weirder than ever. I would really appreciate it
> when you could take a look... I'm pretty experienced at PHP but perhaps you
> know something that I don't know.
>
> We have two different classes: Container and Child. Container objects
> contain a Child object in its $child property. A Child object has a $parent
> property, which contains a *reference* to the Container object by which it
> is held.
> So $containerObject should be the *same* as $containerObject->child->parent.
> To test this Container objects have a $property property. When changing this
> property the difference between one object and identical/cloned objects
> becomes visible.
>
> Now take a look at the following code. The indented text is code, the rest
> are comments. The code for the class Container and class Child are also
> included. Please scroll down or take a look at the attached file.
>
> begin first code snippet --------------------------------
> <?php
>
> /* New Container object created. At the same time it sets a Child object in
> its $child attribute. (This is indicated by passing TRUE.) */
> $testContainer1 = new Container(TRUE);
> /* The Container object is created, the Child object is set and its
> reference to the Container object is set. Now it prints
> $testContainer1->property and $testContainer->child->parent->property. These
> should have an identical value because they should be from the same object
> (not cloned/identical, but the same).
> This is the result:
> property = 'state 1'
> child->parent->property = 'state 1'
> So this is as expected, no problem... yet. */
> $testContainer1->printState();
>
> /* Now $testContainer1's $property property is changed into another value.
> /*
> $testContainer1->property = 'state 2';
> /* Now $testContainer1->child->parent->property should also have value
> 'state 2', but it HAS NOT!
> This is the result:
> property = 'state 2'
> child->parent->property = 'state 1'
> Obviously $testContainer1->child->parent->property is not the same object as
> $testContainer1, but a clone! */
> $testContainer1->printState();
>
> ?>
> end first code snippet --------------------------------
>
> Well, this is the whole problem... Why on earth isn't it a reference, while
> I really did assign it as a reference in the code (see class code).
>
> Now to make the whole thing even weirder, take a short look at the following
> code. It is almost completely the same as above, except that instead of
> giving the Container constructor the command to assign a Child object to the
> $child property, this command is given manually by calling method load() --
> which is the method that Container constructor uses to load the Child
> object.
>
> begin second code snippet --------------------------------
> <?php
>
> /* Here the Container object is created again. But now no TRUE is passed
> because we don't want the Container constructor method to create and assign
> a Child object to the $child property. */
> $testContainer2 = new Container;
> /* In the first code snippet load() is called from the Container constructor
> method. So in fact nothing has changed, except the fact that load() is
> called from the client scope instead of the Container object scope now. */
> $testContainer2->load();
> $testContainer2->printState();
>
> $testContainer2->property = 'state 2';
> /* After $property has been modified again, $testContainer2's state is
> printed again, and now the result is DIFFERENT!!!:
> property = 'loaded state 2'
> child->parent->property = 'loaded state 2'
> This is the CORRECT result!!! This is what we also expected from the first
> code snippet!!! And this while the executed codes are in fact identical!!!
> How on earth is this possible?!? */
> $testContainer2->printState();
>
> ?>
> end second code snippet --------------------------------
>
> Well, this is the contradiction I wanted to show you all. I don't see the
> logics of it all, but ofcourse I could be missing one obvious thing...
> actually I hope so, because I need the construction as in the first code
> snippet.
>
> Below the code for the classes Container en Child.
>
> begin third code snippet --------------------------------
> <?php
>
> class Container
> {
>
> var $children;
> var $property;
>
> function Container($load = FALSE)
> {
> $this->property = 'not loaded';
> if ($load) {
> $this->load();
> }
> }
>
> function load()
> {
> $newChild = new Child(1);
> $this->add(&$newChild);
> $this->property = 'state 1';
> }
>
> function add($child)
> {
> /* Here a reference of $this (the Container object) is assigned to $child's
> $parent attribute. */
> $child->parent = &$this;
> /* Here $child (the newly created Child object) is assigned to the
> container's $child property. */
> $this->child = &$child;
> }
>
> function printState()
> {
> print 'property = \'' . $this->property .
> '\'<BR>' .
> 'child->parent->property = \'' .
> $this->child->parent->property
> . '\'<P>';
> }
>
> }
>
> class Child
> {
>
> var $id;
> var $parent;
>
> function Child($id)
> {
> $this->id = $id;
> }
>
> }
>
> ?>
> end third code snippet --------------------------------
>
> Well that's it. I hope someone can help me on this. I'm not a person who
> asks for help very quick. I prefer finding it out myself, also because I'm
> pretty experienced at PHP. But this is the first time I really can't figure
> out what it is... I really NEEEEED you now :)
>
> Good luck and a lot of thanks in advance,
>
> Tim.
>
> P.S. I'm using PHP4, I do not know this code's reliability and behaviour
> when running it with previous versions.
>
>
> begin 666 complex.php
> M/#]P:' -"@T*8VQA<W,@0V]N=&%I;F5R#0I[#0H)#0H)=F%R("1C:&EL9')E
> M;CL-"@EV87(@)'!R;W!E<G1Y.PT*#0H)9G5N8W1I;VX@0V]N=&%I;F5R*"1L
> M;V%D(#T@1D%,4T4I#0H)>PT*(" @(" @("
> D=&AI<RT^<')O<&5R='D@/2 G
> M;F]T(&QO861E9"<[#0H)(" @(&EF("@D;&]A9"D@>PT*(" @(
> D))'1H:7,M
> M/FQO860H*3L-"B @(" @(" @?0T*"7T-"@T*("
> @(&9U;F-T:6]N(&QO860H
> M*0T*(" @('L-"B @(" @(" @)&YE=T-H:6QD(#T@;F5W($-H:6QD*#$I.PT*
> M(" @(" @(" D=&AI<RT^861D*"1N97=#:&EL9"D[#0H@("
> @(" @("1T:&ES
> M+3YP<F]P97)T>2 ]("=S=&%T92 Q)SL-"B @("!]#0H-"@EF=6YC=&EO;B!A
> M9&0H)&-H:6QD*0T*"7L-"@D))&-H:6QD+3YP87)E;G0@/2 F)'1H:7,[#0H)
> M"21T:&ES+3YC:&EL9" ]("8D8VAI;&0[#0H)?0T*#0H@(" @9G5N8W1I;VX@
> M<')I;G13=&%T92@I#0H@(" @>PT*(" @(" @("!P<FEN="
> G<')O<&5R='D@
> M/2!<)R<@+B D=&AI<RT^<')O<&5R='D@+B G7"<\0E(^)R
> N#0H@(" @(" @
> M(" @("
> G8VAI;&0M/G!A<F5N="T^<')O<&5R='D@/2!<)R<@+B D=&AI<RT^
> M8VAI;&0M/G!A<F5N="T^<')O<&5R='D@+B
> G7"<\4#XG.PT*(" @('T-"@D-
>
> M"GT-"@T*8VQA<W,@0VAI;&0-"GL-"@D-"@EV87(@)&ED.PT*"79A<B
> D<&%R
> M96YT.PT*"0T*"69U;F-T:6]N($-H:6QD*"1I9"D-"@E[#0H)"21T:&ES+3YI
> M9" ]("1I9#L-"@E]#0H)#0I]#0H-"@T*)'1E<W1#;VYT86EN97(R(#T@;F5W
> M($-O;G1A:6YE<BA44E5%*3L-"B1T97-T0V]N=&%I;F5R,BT^<')I;G13=&%T
> M92@I.PT*#0HD=&5S=$-O;G1A:6YE<C(M/G!R;W!E<G1Y(#T@)W-T871E(#(G
> M.PT*)'1E<W1#;VYT86EN97(R+3YP<FEN=%-T871E*"D[#0H-"G!R:6YT("<\
> M2%(^)SL-"@T*)'1E<W1#;VYT86EN97(Q(#T@;F5W($-O;G1A:6YE<CL-"B1T
> M97-T0V]N=&%I;F5R,2T^;&]A9"@I.PT*)'1E<W1#;VYT86EN97(Q+3YP<FEN
> M=%-T871E*"D[#0H-"B1T97-T0V]N=&%I;F5R,2T^<')O<&5R='D@/2
> G<W1A
> M=&4@,B<[#0HD=&5S=$-O;G1A:6YE<C$M/G!R:6YT4W1A=&4H*3L-"@T*/SX-
> !"@``
> `
> end
>
>
> --
> PHP General Mailing List (http://www.php.net/)
> To unsubscribe, visit: http://www.php.net/unsub.php
>