@websiller

Как собрать массив из свойств по цепочке наследования?

Нужно пройтись по цепочке наследования классов и собрать массив из свойства, определенного в каждом из классов:
<?php

class base {
	public function getParent(){
		return ['base'];
	}
}

class class1 extends base {
	public static $arr = ['class1'];

	public function getParent(){
		return array_merge(self::$arr, parent::getParent());
	}
}

class class2 extends class1 {
	public static $arr = ['class2'];
	
}

class class3 extends class2 {
	public static $arr = ['class3'];
	
}

$new = new class3();

echo "<pre>";
print_r ($new->getParent());
echo "</pre>";
// Array
// (
//     [0] => class1
//     [1] => base
// )

В итоге наследуемый метод не вызывается у классов class3 и class2, а переходит сразу к class1. Изначально ожидалось получить такой массив:
Array
(
[0] => class3
[1] => class2
[2] => class1
[3] => base
)
Может есть какой-то другой способ?
  • Вопрос задан
  • 82 просмотра
Решения вопроса 2
BoShurik
@BoShurik
Symfony developer
Вы каждый раз перезаписываете переменную $arr. Цепочку таким образом не получить.

Если вам нужны названия классов, то можно воспользоваться методом getParentAlt

<?php

class base {
    public function getParent(){
        return ['base'];
    }

    public function getParentAlt(){
        $class = static::class;
        $classes = [
            $class
        ];
        while ($parent = get_parent_class($class)) {
            $class = $parent;
            $classes[] = $class;
        }

        return $classes;
    }
}

class class1 extends base {
    public function getParent(){
        return array_merge(['class1'], parent::getParent());
    }
}

class class2 extends class1 {
    public function getParent(){
        return array_merge(['class2'], parent::getParent());
    }
}

class class3 extends class2 {
    public function getParent(){
        return array_merge(['class3'], parent::getParent());
    }
}

$new = new class3();

print_r ($new->getParent());
print_r ($new->getParentAlt());
Ответ написан
alexey-m-ukolov
@alexey-m-ukolov Куратор тега PHP
Проблема в том, что в каждом классе метод getParent() должен быть явно определён, иначе полную цепочку не получить. Но поскольку реализация этого метода абсолютно идентична, её можно вынести в трейт:
spoiler
<?php
trait ParentAware {
  public function getParent(){
    return array_merge(self::$arr, parent::getParent());
  }
}

class base {
  public function getParent(){
    return ['base'];
  }
}

class class1 extends base {
  use ParentAware;

  public static $arr = ['class1'];
}

class class2 extends class1 {
  use ParentAware;

  public static $arr = ['class2'];
}

class class3 extends class2 {
  use ParentAware;

  public static $arr = ['class3'];
}

var_dump((new class3)->getParent());

//array(4) {
//  [0] => string(6) "class3"
//  [1] => string(6) "class2"
//  [2] => string(6) "class1"
//  [3] => string(4) "base"
//}


Хотя, есть и более простое решение с использованием class_parents():
spoiler
<?php
class base
{
    public static $arr = ['base'];

    public function getParent()
    {
        $parentClasses = class_parents($this);

        $result = static::$arr;

        foreach ($parentClasses as $parentClass) {
            $result = array_merge($result, $parentClass::$arr);
        }

        return $result;
    }
}

class class1 extends base
{
    public static $arr = ['class1'];
}

class class2 extends class1
{
    public static $arr = ['class2'];
}

class class3 extends class2
{
    public static $arr = ['class3'];
}

$new = new class3();

var_dump($new->getParent());

//array(4) {
//  [0] => string(6) "class3"
//  [1] => string(6) "class2"
//  [2] => string(6) "class1"
//  [3] => string(4) "base"
//}

Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы