Strange PHP Reaction

81 Views Asked by At

I'm getting some wierd reactions when running this script.

<?php

    error_reporting(E_ALL);

    class A {
        protected $varOne = array(
            "subVar1" => "",
            "subVar2" => "",
            "subVar3" => "",
            "subVar4" => "",
        );

        public function init() {
            $b = new B();
            $b->funTest();
            echo( "One Two Three" );
            echo( "<br />" );
            print_r( $this->varOne );
            echo( "<br />" );
        }

        protected function setValue( $key, $value ) {
            $this->varOne[$key] = $value;
        }
    }

    class B extends A {
        public function funTest() {
            $this->setValue( "subVar1", "21" );
            $this->setValue( "subVar2", "22" );
            $this->setValue( "subVar3", "23" );
            $this->setValue( "subVar4", "24" );
            echo( "Four Five Six" );
            echo( "<br />" );
            print_r( $this->varOne );
            echo( "<br />" );
        }
    }

    $a = new A();
    $a->init();

Now the output here troubles me.

OUTPUT:
Four Five Six // As Expected
Array ( [subVar1] => 21 [subVar2] => 22 [subVar3] => 23 [subVar4] => 24 ) // As Expected
One Two Three // As Expected
Array ( [subVar1] => [subVar2] => [subVar3] => [subVar4] => ) // Wait, WTF?

Why are the variables empty when called from class A?

Also when setting the visibility to private, the variable is NULL/EMPTY when called from class B.

EDIT:

This seams to give me my needed result, Thanks to all for the help.

<?php

error_reporting(E_ALL);

class A {
    protected $varOne = array(
        "subVar1" => "",
        "subVar2" => "",
        "subVar3" => "",
        "subVar4" => "",
    );

    public function init() {
        echo( "One Two Three" );
        echo( "<br />" );
        print_r( $this->varOne );
        echo( "<br />" );
        $b = new B();
        $this->varOne = $b->funTest();
        echo( "One Two Three" );
        echo( "<br />" );
        print_r( $this->varOne );
        echo( "<br />" );
    }

    protected function setValue( $key, $value ) {
        $this->varOne[$key] = $value;
    }
}

class B extends A {
    public function funTest() {
        $this->setValue( "subVar1", "21" );
        $this->setValue( "subVar2", "22" );
        $this->setValue( "subVar3", "23" );
        $this->setValue( "subVar4", "24" );
        return( $this->varOne );
    }
}

$a = new A();
$a->init();
1

There are 1 best solutions below

4
On

As the comments point out: with the new keyword you create a new instance of B and anything referring $this will only update values inside the B instance and values inside A remain unchanged.

To update A from within B without copy-pasting the method you could do something like below. I adapted the code with a $target parameter so you could pass along $this with funTest

<?php

error_reporting(E_ALL);

class A {
    protected $varOne = array(
        "subVar1" => "",
        "subVar2" => "",
        "subVar3" => "",
        "subVar4" => "",
    );

    public function init() {
        $b = new B();
        $b->funTest($this);
        echo( "One Two Three" );
        echo( "<br />" );
        print_r( $this->varOne );
        echo( "<br />" );
    }

    protected function setValue( $key, $value ) {
        $this->varOne[$key] = $value;
    }
}

class B extends A {
    public function funTest($target) {
        $target->setValue( "subVar1", "21" );
        $target->setValue( "subVar2", "22" );
        $target->setValue( "subVar3", "23" );
        $target->setValue( "subVar4", "24" );
        echo( "Four Five Six" );
        echo( "<br />" );
        print_r( $target->varOne );
        echo( "<br />" );
    }
}

$a = new A();
$a->init();

This gives your expected behaviour:

Four Five Six
Array ( [subVar1] => 21 [subVar2] => 22 [subVar3] => 23 [subVar4] => 24 ) 
One Two Three
Array ( [subVar1] => 21 [subVar2] => 22 [subVar3] => 23 [subVar4] => 24 )