How to inherit array properties of parent class by array merge?

I often use properties in my classes that store an array of parameters. I would like to be able to somehow combine these parameters from the default values ​​declared in the parent class.

I have demonstrated with some code.

class A
{
    public $options = array('display'=>false,'name'=>'John');
}

class B extends A
{
    public $options = array('name'=>'Mathew');
}

      

Now when I create B

I would like to $options

contain the concatenated array fromA::options

Now this is happening.

$b = new B();
print_r($b);
array('name'=>'Mathew');

      

I would like something like this with help array_merge_recursive()

.

array('display'=>false,'name'=>'Mathew');

      

  • Maybe this is something I could do in the constructor?
  • Can this behavior be done class A

    ? So I don't always have to implement the same code in all subclasses.
  • Is it possible to use reflection to automatically look up array properties in both classes and combine them?
+3


source to share


3 answers


I realize I changed my interface from a public variable to a method, but maybe it works for you. Be aware that adding a naive method setOps($ops)

can unexpectedly work if you allow parent operations to continue merging.

class A
{
    private $ops = array('display'=>false, 'name'=>'John');
    public function getops() { return $this->ops; }
}
class B extends A
{
    private $ops = array('name'=>'Mathew');
    public function getops() { return array_merge(parent::getOps(), $this->ops); }
}
class c extends B
{
    private $ops = array('c'=>'c');
    public function getops() { return array_merge(parent::getOps(), $this->ops); }
}

$c = new C();
print_r($c->getops());

      



out:

Array
(
    [display] => 
    [name] => Mathew
    [c] => c
)

      

+5


source


In addition to the previous answers, another approach that might be applicable in some cases would be using PHP Reflection or built-in class functions. Here's a basic example using the latter:



class Organism
{
    public $settings;
    public $defaults = [
        'living' => true,
        'neocortex' => false,
    ];
    public function __construct($options = [])
    {
        $class = get_called_class();
        while ($class = get_parent_class($class)) {
            $this->defaults += get_class_vars($class)['defaults'];
        }
        $this->settings = $options + $this->defaults;
    }
}
class Animal extends Organism
{
    public $defaults = [
        'motile' => true,
    ];
}
class Mammal extends Animal
{
    public $defaults = [
        'neocortex' => true,
    ];
}

$fish = new Animal();
print_r($fish->settings); // motile: true, living: true, neocortex: false
$human = new Mammal(['speech' => true]);
print_r($human->settings); // motile: true, living: true, neocortex: true, speech: true

      

+3


source


You can use a simple template like:

abstract class Parent {

    protected $_settings = array();

    protected $_defaultSettings = array(
        'foo' => 'bar'
    );

    public __construct($settings = array()) {
        $this->_settings = $settings + $this->_defaultSettings;
    }

}

      

Thus, it is easy to change the default values ​​used in child classes:

class Child extends Parent {

    protected $_defaultSettings = array(
        'something' => 'different';
    );

}

      

Or apply something more complex:

class OtherChild extends Parent {

    function __construct($settings = array()) {
        $this->_defaultSettings = Configure::read('OtherChild');
        return parent::__construct($settings);
    }

}

      

Merging variables

Cake does have a function for merging variables . It is used for controller properties like components, helpers, etc. But be careful when applying this function to any trivial arrays - you may find that it doesn't quite do what you want / expect.

+2


source







All Articles