5

I have some classes that extend each other, each time adding more properties.

Now I need to get a list of all properties of a class, but in the order that they were declared, with the properties of the parent class first.

For example :

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));

This gives :

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

but I want :

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

Is there any way this could be achieved?

UPDATE: The reason I need this, is because I'm converting a file that uses the STEP (EXPRESS ISO 10303-21) format (and back!). (See this for more information : http://en.wikipedia.org/wiki/ISO_10303-21) This format is some kind of serialized objects structure. I recreated all object classes in PHP, but since in STEP the order of the properties is crucial, I need the exact same order of the properties.

rochb
  • 2,249
  • 18
  • 26
Dylan
  • 9,129
  • 20
  • 96
  • 153
  • 1
    d is first because it's on the descendant. put it on the parent and it'll be first. otherwise, you'll need to reorder the array manually. – crush Jul 03 '13 at 18:29
  • 3
    Why is the order so important? You can still access $d directly: $test->d – Horen Jul 03 '13 at 18:30
  • 2
    I realize this possibly doesn't help answer the question, but out of curiosity, and if you're able to do so succinctly, could you provide your use case? I can't imagine for what reason you would want to do this, and I wonder if perhaps the fact that you want to do so indicates that you're already doing something in the 'wrong' way. – Mark Amery Jul 03 '13 at 18:35
  • A solution would be to walk the inheritance chain to the earliest ancestor, then reverse walk it, adding the properties to an array. – crush Jul 03 '13 at 18:39
  • To answer your question, if you need the order based on the inheritance, you need to walk the inheritance per reflection. See as well: http://stackoverflow.com/questions/11821137/get-the-defining-class-for-a-constant-in-php - Please edit your questions example becuase as you've demonstrated so far you're using the *wrong* method. Asking a question should be a bit more than just complaining that function xy doesn't do the job. Also it's not clear *why* you need that. – hakre Jul 03 '13 at 18:42

1 Answers1

3

Is there any way this could be achieved?

It's not totally clear what exactly you need (and what your motivation is which would have been good to know to give concrete suggestions), but what you're looking for is possible by using PHP Reflection.

You do so by getting all ancestor classes until the root class, and then you read all properties with it on all these classes. See the ReflectionClass class with it's ReflectionClass::getDefaultProperties() method.

See as well

Hope this is helpful, let me know if you run into any problems with that.

Example:

<?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);

Program Output:

Array
(
    [property] => 1
    [ads] => 
    [child] => 1
)
Community
  • 1
  • 1
hakre
  • 193,403
  • 52
  • 435
  • 836
  • Thanks, I'll try to implement this. I just hope this will not slow down things too much, because the file can contain millions of objects! – Dylan Jul 03 '13 at 19:01
  • Well, then you should keep that cached. This should only take a little memory per each class, I bet you don't have a million different classes, right? – hakre Jul 03 '13 at 19:03
  • Problem is that `getDefaultProperties()` also gets all the inherited properties as well. – crush Jul 03 '13 at 19:09
  • @crush: In this case, you only need to union then PHP won't overwrite the parent ones, so these duplicates are actually a non-issue. Otherwise: My link in the comment above under the question shows how to substract those in case this would be needed. – hakre Jul 03 '13 at 19:12
  • Well, you can store those 1000 defines to disk with var_export once you've build them all. I don't think this is much of an overhead. Sure it is some work to do, but nothing that should bring your routine to death. – hakre Jul 03 '13 at 19:13
  • You just saved my day! – TCB13 Jul 10 '14 at 16:45