It is kind of hard for me to explain what I am trying to do so I will just provide an example
class A {
static $data = ['a'];
static function getData() { return static::$data; }
}
class B extends A {
static $data = ['b'];
}
class C extends B {
static $data = ['c'];
}
class D extends B {
static $data = ['d'];
}
$a = new A;
$b = new B;
$c = new C;
$d = new D;
$a::getData(); // Output: Array('a'), Expected: Array('a');
$b::getData(); // Output: Array('b'), Expected: Array('a', 'b');
$c::getData(); // Output: Array('c'), Expected: Array('a', 'b', 'c');
$c::getData(); // Output: Array('d'), Expected: Array('a', 'b', 'd');
Is this possible at all?
EDIT: I have my data objects and each object has a set of rules for its properties. For example a User object has a property name which can be maximum 10 symbols, I define this in the user class' rules and then all user objects will obey the rule when their property name is about to be changed. The rules array is static because they apply to all objects of this class. However when I inherit it for example in a VIP user then the VIP will need to have additional rules for properties that the basic user doesn't have. I need to be able to extend the rules array but if I define such an array in the child class it just overwrites the parent rules which I also need.
So yes, there is a way to do it with only parent class method:
class A
{
public static $data = ['a'];
public static function getData()
{
$result = static::$data;
$class = get_called_class();
while ($class = get_parent_class($class)) {
$result = array_merge($result, $class::$data);
}
return $result;
}
}
class B extends A
{
public static $data = ['b'];
}
class C extends B
{
public static $data = ['c'];
}
class D extends C
{
public static $data = ['d'];
}
Demo here.
If order matters, then change merge arguments order (right now it will be like it is in class hierarchy chain - from child to parent)
Or, utilize class_parents()
class A
{
public static $data = ['a'];
public static function getData()
{
$classes = [get_called_class()]; //no class with name "0"
$classes += class_parents($classes[0]);
return call_user_func_array('array_merge',
array_map(
function($class) {
return $class::$data;
},
$classes
)
);
}
}
Demo here. This is even shorter way. So it can be done with plain array mapping. Unfortunately, current class has to be added manually to the iterated hierarchy array.
This will achieve what you want
class A {
static $data = ['a'];
static function getData() { return self::$data; }
}
class B extends A {
static $data = ['b'];
static function getData() { return array_merge(parent::getData(), self::$data); }
}
class C extends B {
static $data = ['c'];
static function getData() { return array_merge(parent::getData(), self::$data); }
}
class D extends B {
static $data = ['d'];
static function getData() { return array_merge(parent::getData(), self::$data); }
}
$a = new A;
$b = new B;
$c = new C;
$d = new D;
var_dump($a::getData()); // Array('a');
var_dump($b::getData()); // Array('a', 'b');
var_dump($c::getData()); // Array('a', 'b', 'c');
var_dump($d::getData()); // Array('a', 'b', 'd');
Demo
though there's probably a slightly cleaner way of doing it defining getData() only in class A
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