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
[EMAIL PROTECTED]*#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

Reply via email to