someSyl
someSyl

Reputation: 21

get_class_var on child class

I have the following setup:

abstract class AParentLy{
   private $a;
   private $b;

   function foo(){
      foreach(get_class_vars(get_called_class()) as $name => $value){
         echo "$name holds $value";
      }
   }
}

class ChildClass extends AParentLy{
   protected $c='c';
   protected $d='d';
}

$object = new ChildClass();
$object->foo();

What I want it to output is:

c holds c
d holds d

What it does output is:

c holds c
d holds d
a holds
b holds

The get_called_class() method correctly outputs "ChildClass"

I'm fairly new to class inheritance in PHP and from what I can gather the problem lies somewhere in the so scope. But I can't figure out how to make it work.

(The somewhat questionable solution would be to just go ahead and add a great big if($name!='a' && $name!='b' ...~ into the mix. But I'm sure there must be another, more sane and stable way to do this)

Upvotes: 1

Views: 1400

Answers (4)

galchen
galchen

Reputation: 5290

class Parent1 {
   //private $a;
   //private $b;

   function foo(){
      foreach(get_object_vars($this) as $name => $value){
         echo "$name holds $value";
      }
   }
}

class Child1 extends Parent1 {
   protected $c='c';
   protected $d='d';
}

Parent is a reserved name. in class Parent1 you can see $a and $b so removed. changed $c/$c to protected.

the other solution would be:

class Parent1 {
   private $a;
   private $b;
}

class Child1 extends Parent1 {
   private $c='c';
   private $d='d';

   function foo(){
      foreach(get_object_vars($this) as $name => $value){
         echo "$name holds $value<br>";
      }
   }
}

putting foo in Child

EDIT

Sorry to wake an old post. I think i have a preferable solution (actually 2 solutions) for this: The first one is to use a middle class that will create a barrier between the parent and the child:

abstract class Parent1 {
    private $a;
    private $b;
    abstract function foo();
}
class ParentClone1 {
    function foo(){
        foreach(get_object_vars($this) as $name => $value){
            echo "$name holds $value<br />";
        }
    }
}

class Child1 extends ParentClone1 {
    protected $c='c';
    protected $d='d';
}
$c = new Child1();
$c->foo();
// c holds c
// d holds d

The other solution is to use visibility:

If you call get_class_vars()/get_object_vars() from inside a class, it sees all the variables (including private/protected). If you run it from outside it will only see public:

function get_object_vars_global($class){
    return get_object_vars($class);
}
abstract class Parent1 {
    private $a;
    private $b;

    function foo(){
        foreach(get_object_vars_global($this) as $name => $value){
            echo "$name holds $value<br />";
        }
    }

}

class Child1 extends Parent1 {
    public $c='c';
    public $d='d';
}

$c = new Child1();
$c->foo();

since this will result in putting class fields as public, I'd go with the first solution.

Upvotes: 1

someSyl
someSyl

Reputation: 21

Had another go at the whole experiment this question was a part of.

The eventual solution (just in case anyone stumbles over this and has the same problem) I came to was to create the following method within the parent class:

function get_properties(){
    foreach(get_class_vars(get_called_class()) as $name => $value){
        if(!in_array($name,array_keys(get_class_vars('Parent')))){
            $r[$name]=$this->$name;
        }   
    }
    return $r;
}

with this you get every parameter (and their value) of the child class without any of the parent class. You'll have to change the function a bit if you ever change the class name, but at least for me this was a workable solution.

Upvotes: 1

Bjoern
Bjoern

Reputation: 16304

First some basic mistakes:

  1. Don't use a $ in a function name (here: $foo), this will result into a syntax error.
  2. You shouldn't name a class Parent, because it is a reserved word. Calling this would result into an error like Fatal error: Cannot use 'Parent' as class name as it is reserved

There is a good example how it works in the php manual, and there can be found this important sentence, which answers your question:

Class members declared public can be accessed everywhere. Members declared protected can be accessed only within the class itself and by inherited and parent classes. Members declared as private may only be accessed by the class that defines the member.

Upvotes: -1

corretge
corretge

Reputation: 1759

Change the visibility of Child's properties to PROTECTED.

When properties are private, its not visibles.

More info at:

http://php.net/manual/en/language.oop5.visibility.php

Upvotes: 2

Related Questions