# Private properties, Inheritance, Reflection (5.3)

- Thread: https://externals.io/message/43618
- Original archive: https://news-web.php.net/php.internals/43618
- Started by Roman Borschel on 2009-04-03T20:37:45+00:00
- Messages: 9
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #43618 — Roman Borschel — 2009-04-03T20:37:45+00:00

URL: https://externals.io/message/43618#43618

Hi,

i've got a little question that involves private properties,  
inheritance and Reflection with PHP 5.3 RC1.

Given the following simple classes

class Foo {
     private $foo = 'value';
     public function getFoo() { return $this->foo; }
}
class Bar extends Foo {}

Obviously, given an instance of Bar, say $bar, $bar->getFoo() returns  
'value'.

Now the question: How do I get at this value using reflection, given  
an instance of Bar?

$class = new \ReflectionClass('Foo');
$fooProp = $class->getProperty('foo');
$fooProp->setAccessible(true);
$bar = new Bar;
$value = $fooProp->getValue($bar);
var_dump($value); // `NULL` 
var_dump($bar); // array(1) { ["�Foo�foo"]=>  string(5) "value" }

How do I get at the value exposed by "var_dump($bar);" through  
reflection?
Obviously, I can't upcast like this: "$fooProp->getValue((Foo)$bar)".

I'm asking here because I have the bad feeling that this is might not  
(yet?) be possible.

Thanks!

Roman

---

## #43619 — johannes@php.net — 2009-04-03T23:53:16+00:00

URL: https://externals.io/message/43618#43619 · In reply to: #43618

> Given the following simple classes
> 
> class Foo {
>      private $foo = 'value';
>      public function getFoo() { return $this->foo; }
> }
> class Bar extends Foo {}
> 
> Obviously, given an instance of Bar, say $bar, $bar->getFoo() returns  
> 'value'.
> 
> Now the question: How do I get at this value using reflection, given  
> an instance of Bar?

class Foo { private $foo = "value"; }
class Bar extends Foo {}
$f = new Foo;
// we have to know the context, as there might be multiple foo properties
$r = new ReflectionProperty("Foo", "foo");
$r->setAccessible(true);
var_dump($r->getValue($f));

works for me.

johannes

---

## #43620 — Roman Borschel — 2009-04-04T05:34:09+00:00

URL: https://externals.io/message/43618#43620 · In reply to: #43619

Hi,



> 
> > […]
>
> class Foo { private $foo = "value"; }
> class Bar extends Foo {}
> $f = new Foo;
> // we have to know the context, as there might be multiple foo  
> properties
> $r = new ReflectionProperty("Foo", "foo");
> $r->setAccessible(true);
> var_dump($r->getValue($f));
>
> works for me.
>
> johannes

Thanks for your answer. Yes, this works, but here $f is an instance of  
Foo, not Bar. When you make it an instance of Bar you get NULL. I  
think this is not correct, is it?
Given that we have a ReflectionProperty of class Foo at hand, from my  
understanding it should look at an instance of Bar as a Foo and return  
the value. Am I missing something?

Regards

Roman

---

## #43621 — Roman Borschel — 2009-04-04T07:02:09+00:00

URL: https://externals.io/message/43618#43621 · In reply to: #43620

For what it matters, the same thing in Java returns the expected result:

Class clazz = Foo.class;
Field fooProp = clazz.getDeclaredField("foo");
fooProp.setAccessible(true);
Bar bar = new Bar();
String value = (String)fooProp.get(bar);
System.out.println(value);

So is this a bug or some weird behavior I just don't understand yet?

Roman



> Hi,
>
> 
>
> > […]
>
> Thanks for your answer. Yes, this works, but here $f is an instance  
> of Foo, not Bar. When you make it an instance of Bar you get NULL. I  
> think this is not correct, is it?
> Given that we have a ReflectionProperty of class Foo at hand, from  
> my understanding it should look at an instance of Bar as a Foo and  
> return the value. Am I missing something?
>
> Regards
>
> Roman

---

## #43622 — Roman Borschel — 2009-04-04T11:08:26+00:00

URL: https://externals.io/message/43618#43622 · In reply to: #43621

Hi,

Despite my almost non-existant C-skills I managed to put together a  
"patch" (or what I think is a patch) that does not break any tests.

My "patch" is simply to replace the first argument of  
zend_update_property/zend_read_property in ext/php_reflection.c like  
this:

within the getValue definition:
old: member_p = zend_read_property(Z_OBJCE_P(object), object,  
prop_name, strlen(prop_name), 1 TSRMLS_CC);
new: member_p = zend_read_property(ref->ce, object, prop_name,  
strlen(prop_name), 1 TSRMLS_CC);

within the setValue definition:
old: zend_update_property(Z_OBJCE_P(object), object, prop_name,  
strlen(prop_name), value TSRMLS_CC);
new: zend_update_property(ref->ce, object, prop_name,  
strlen(prop_name), value TSRMLS_CC);

So simply replacing Z_OBJCE_P(object) with ref->ce.

I assume "ce" stands for "class entry" and is a zend_class_entry. So  
instead of taking the zend_class_entry from the object, we take the  
one associated with the reflection property (at least thats what i  
assume it does).

I will now try to create a new test for this issue, taking of the  
existing tests as a template.

Any comments appreciated.

Roman



> For what it matters, the same thing in Java returns the expected  
> result:
>
> Class clazz = Foo.class;
> Field fooProp = clazz.getDeclaredField("foo");
> fooProp.setAccessible(true);
> Bar bar = new Bar();
> String value = (String)fooProp.get(bar);
> System.out.println(value);
>
> So is this a bug or some weird behavior I just don't understand yet?
>
> Roman
>
> 
>
> > […]

---

## #43623 — johannes@php.net — 2009-04-04T11:08:56+00:00

URL: https://externals.io/message/43618#43623 · In reply to: #43620

> Thanks for your answer. Yes, this works, but here $f is an instance of  
> Foo, not Bar. When you make it an instance of Bar you get NULL. I  
> think this is not correct, is it?
> Given that we have a ReflectionProperty of class Foo at hand, from my  
> understanding it should look at an instance of Bar as a Foo and return  
> the value. Am I missing something?

Damn, you're right, was too late yesterday evening for me :-)

This really looks like a bug in this feature.

johannes

---

## #43625 — johannes@php.net — 2009-04-04T11:23:11+00:00

URL: https://externals.io/message/43618#43625 · In reply to: #43622

> My "patch" is simply to replace the first argument of  
> zend_update_property/zend_read_property in ext/php_reflection.c like  
> this:
[...]
> So simply replacing Z_OBJCE_P(object) with ref->ce.

yes, that was what i was thinking about, too after my first look, but I
have no test environment on this box, will try it later, if nobody steps
in tests&commits :-)

johannes

---

## #43626 — Roman Borschel — 2009-04-04T16:02:27+00:00

URL: https://externals.io/message/43618#43626 · In reply to: #43625

Hi,

i created 2 patches that are attached to this mail, one to fix the  
issue and the other to add tests for it (I added them into  
reflectionProperty_setAccessible.phpt).

Roman

---

## #43627 — Sebastian Bergmann — 2009-04-04T16:10:51+00:00

URL: https://externals.io/message/43618#43627 · In reply to: #43626

Roman Borschel schrieb:
> i created 2 patches that are attached to this mail

 Your attachments did not make it to the list. No worries, though, I
 committed a patch together with updated tests earlier.

-- 
Sebastian Bergmann                    Co-Founder and Principal Consultant
http://sebastian-bergmann.de/                           http://thePHP.cc/
