Question

class A {
    protected $a = 'aaa';
}

class B extends A {
    protected $a = 'bbb';
    public function __construct(){
       echo parent::$a; // Fatal error: Access to undeclared static property: A::$a in main.php on line 11
    }
}

$b = new B();

I want to access $a variable from class A in constructor of class B. Be aware that $a variable is overwritten in class B. How can I access parent::$a?

Was it helpful?

Solution

The only way to do this would be to declare $a as static:

protected static $a = 'aaa';

But that will make the value of parent::$a the same for all instances. If you want separate values, this cannot be done, and you'd be better off renaming the variables, eg one is $a and the other is $b.

OTHER TIPS

class A {
    protected $a = 'aaa';
}

class B extends A {
    protected $a = 'bbb';
    public function __construct(){
       echo parent::$a; // Fatal error: ...
    }
}

$b = new B();

How can I access parent::$a?

You cant, parent::$a means you are trying to access a static property from a parent class.

instead of doing this,use the constructor to modify $a

class B extends A {
    public function __construct(){
       // do something with $this->a value here;
    }
}

or you'll always overwrite $a if your redeclare it as a property in B.

I just read your comment so I understand your use case a little better now. If you are adding/merging configurations in inheriting classes I'd suggest an alternative approach, adding some behaviour.

As you confirmed above:

  • class A has a default configuration
  • class B can optionally pass in config values that can update/add to the default config

In this case, something like this could work for you:

class A
{
    protected $config = array(
        'foo' => 'foo',
        'bar' => 'bar',
        'baz' => 'baz',
    );

    public function __construct(array $config = array())
    {
        $this->config = array_merge($this->config, $config);
    }

    public function getConfig()
    {
        return $this->config;
    }
}

class B extends A
{
    // implement
}

$b = new B(array(
    'foo' => 'OVERWRITTEN',
    'new' => 'NEW',
));

print_r($b->getConfig());

Yields:

Array
(
    [foo] => OVERWRITTEN
    [bar] => bar
    [baz] => baz
    [new] => NEW
)

You can also overwrite your default config in the same way when using class A directly. Alternatively, instead of implementing the merge in __construct() you could implement that as a setConfig() method.

Hope this helps :)

EDIT

I just want to add one more thing: if your config is a multidimensional array, you will have to change how you merge arrays. At first glance array_merge_recursive() might seem like the obvious candidate. However:

$old = array(
    'foo' => 'foo',
    'bar' => 'bar',
    'baz' => array(
        'baa' => 'baa',
        'boo' => 'boo',
    ),
);

$new = array(
    'foo' => 'FOO',
    'baz' => array(
        'baa' => 'BAA',
    ),
    'new' => 'new'
);

$merge = array_merge_recursive($old, $new);
print_r($merge);

actually yields:

Array
(
    [foo] => Array
        (
            [0] => foo
            [1] => FOO
        )

    [bar] => bar
    [baz] => Array
        (
            [baa] => Array
                (
                    [0] => baa
                    [1] => BAA
                )

            [boo] => boo
        )

    [new] => new
)

Probably not what you are looking for! Instead use array_replace_recursive():

$merge = array_replace_recursive($old, $new);
print_r($merge);

This yields:

Array
(
    [foo] => FOO
    [bar] => bar
    [baz] => Array
        (
            [baa] => BAA
            [boo] => boo
        )

    [new] => new
)

@Darragh I made it little different because I didn't want to change my constructors:

abstract class A
{
    protected $a = array('a' => 1, 'b' => 2);

    public function __construct()
    {
        $this->mixA();
    }

    protected function a()
    {
        return array();
    }

    protected function mixA()
    {
        foreach ($this->a() as $key => $val) {
            $this->a[$key] = $val; // $val can be an array too (in my case it is)
        }
    }
}

class B extends A
{
    protected function a()
    {
        return array(
            'b' => 'new value',
            'c' => 'new variable'
        );
    }

    public function dumpA()
    {
        var_dump($this->a);
    }
}

$b = new B();
$b->dumpA();

So now if I want to change my default configs I just overwrite a() method. mixA() method can be expanded as needed.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top