Как получить иерархический порядок свойств с помощью get_object_vars?

У меня есть несколько классов, которые расширяют друг друга, каждый раз добавляя новые свойства.

Теперь мне нужно получить список всех свойств класса, но в том порядке, в котором они были объявлены, сначала со свойствами родительского класса.

Например :

class foo {
    public $a = 1;
    public $c = 2;
    public $d = 3;
}

class foo2 extends foo {
    public $b = 4;
}

$test = new foo2;

var_dump(get_object_vars($test));

Это дает :

array(4) { ["b"]=> int(4) ["a"]=> int(1) ["c"]=> int(2) ["d"]=> int(3) } 

но я хочу :

array(4) { ["a"]=> int(1) ["c"]=> int(2) ["d"]=> int(3) ["b"]=> int(4) } 

Можно ли как-то этого добиться?

ОБНОВЛЕНИЕ: Причина, по которой мне это нужно, заключается в том, что я конвертирую файл, использующий формат STEP (EXPRESS ISO 10303-21) (и обратно!). (Дополнительную информацию см. здесь: http://en.wikipedia.org/wiki/ISO_10303-21) Этот формат представляет собой некоторую структуру сериализованных объектов. Я воссоздал все классы объектов в PHP, но поскольку в STEP порядок свойств имеет решающее значение, мне нужен точно такой же порядок свойств.


person Dylan    schedule 03.07.2013    source источник
comment
d является первым, потому что он находится в потомке. положите его на родителя, и он будет первым. в противном случае вам потребуется изменить порядок массива вручную.   -  person crush    schedule 03.07.2013
comment
Почему порядок так важен? Вы по-прежнему можете обращаться к $d напрямую: $test-›d   -  person Horen    schedule 03.07.2013
comment
Я понимаю, что это, возможно, не поможет ответить на вопрос, но из любопытства, и если вы можете сделать это кратко, не могли бы вы предоставить свой вариант использования? Я не могу представить, по какой причине вы хотели бы это сделать, и мне интересно, возможно, тот факт, что вы хотите это сделать, указывает на то, что вы уже делаете что-то «неправильным» способом.   -  person Mark Amery    schedule 03.07.2013
comment
Решением было бы пройти по цепочке наследования до самого раннего предка, а затем пройти по ней в обратном порядке, добавив свойства в массив.   -  person crush    schedule 03.07.2013
comment
Чтобы ответить на ваш вопрос, если вам нужен порядок, основанный на наследовании, вам нужно пройти по наследству для каждого отражения. См. также: stackoverflow.com/questions/11821137/. Пожалуйста, отредактируйте пример с вопросами, потому что, как вы уже продемонстрировали, вы используете неправильный метод. Задать вопрос — это нечто большее, чем просто пожаловаться на то, что функция xy не выполняет свою работу. Также непонятно, зачем вам это нужно.   -  person hakre    schedule 03.07.2013


Ответы (1)


Можно ли как-то этого добиться?

Не совсем понятно, что именно вам нужно (и какова ваша мотивация, которую было бы полезно знать, чтобы давать конкретные предложения), но то, что вы ищете, возможно с помощью Отражение PHP.

Вы делаете это, получая все классы-предки до корневого класса, а затем считываете все свойства с ним во всех этих классах. См. класс ReflectionClass с его ReflectionClass::getDefaultProperties().

Смотрите также

Надеюсь, это будет полезно, дайте мне знать, если у вас возникнут какие-либо проблемы с этим.

Пример:

<?php

class root {
   public $property = 1;
}

class parentClass extends root {
   public $ads = FALSE;
}

class child extends parentClass {
   public $child = TRUE;
}

$class = 'child';

$chain = array_reverse(class_parents($class), true) + [$class => $class];

$props = [];

foreach($chain as $class)
{
     $props += (new ReflectionClass($class))->getDefaultProperties();    
}

print_r($props);

Выход программы:

Array
(
    [property] => 1
    [ads] => 
    [child] => 1
)
person hakre    schedule 03.07.2013
comment
Спасибо, попробую реализовать. Я просто надеюсь, что это не сильно замедлит работу, потому что файл может содержать миллионы объектов! - person Dylan; 03.07.2013
comment
Что ж, тогда вы должны хранить это в кэше. Это должно занимать немного памяти на каждый класс, держу пари, у вас нет миллиона разных классов, верно? - person hakre; 03.07.2013
comment
Проблема в том, что getDefaultProperties() также получает все унаследованные свойства. - person crush; 03.07.2013
comment
@crush: в этом случае вам нужно только объединиться, тогда PHP не перезапишет родительские, поэтому эти дубликаты на самом деле не проблема. В противном случае: моя ссылка в комментарии выше под вопросом показывает, как их вычесть, если это понадобится. - person hakre; 03.07.2013
comment
Что ж, вы можете сохранить эти 1000 определений на диск с помощью var_export, как только вы их все соберете. Не думаю, что это большие накладные расходы. Конечно, это требует некоторой работы, но ничего такого, что могло бы убить вашу рутину. - person hakre; 03.07.2013
comment
Вы только что спасли мой день! - person TCB13; 10.07.2014