I have a following class hierarchy, which shown in a reproduction script below:
<?php
header('Content-Type: text/plain');
class A
{
public $config = array(
'param1' => 1,
'param2' => 2
);
public function __construct(array $config = null){
$this->config = (object)(empty($config) ? $this->config : array_merge($this->config, $config));
}
}
class B extends A
{
public $config = array(
'param3' => 1
);
public function __construct(array $config = null){
parent::__construct($config);
// other actions
}
}
$test = new B();
var_dump($test);
?>
Output:
object(B)#1 (1) {
["config"]=>
object(stdClass)#2 (1) {
["param3"]=>
int(1)
}
}
What I wanted, is that A::$config not be overriden by B::$config. There might be a lot of descendant classes from B, where I would like to change $config, but I need that those $config values to merge / overwrite if match $config values of all it's parents.
Q: How can I do that ?
I've tried to use array_merge() but in non-static mode those variables just override themselves. Is there a way to achieve merge effect for class tree without static (late static binding) ?
Instead of declaring a $config property with values that you're going to change in the constructor, it's better to declare those values as default values. This is also described in Orangepill's answer:
class A
{
public $config;
private $defaults = array(
'param1' => 1,
'param2' => 2,
);
public function __construct(array $config = array())
{
$this->config = (object)($config + $this->defaults);
}
}
A few twists there; by declaring the default value of the $config constructor argument as an empty array, you can simplify your code by using array operators like I did above. Undefined keys in $config are filled in by $this->defaults.
The extended class will look very similar:
class B extends A
{
private $defaults = array(
'param3' => 1
);
public function __construct(array $config = array())
{
parent::__construct($config + $this->defaults);
}
}
You can restructure how your extended class is instantiated
class B extends A
{
private $defaults = array('param3' => 1);
public function __construct(array $config = null){
parent::__construct($config?array_merge($this->defaults, $config):$this->defaults);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With