Cover image for post Reflecting private properties

Reflecting private properties

I recently stumbled over reflecting private properties in PHP again. As you might know, this was not possible until now and if you tried this:

<?php class Foo { private $bar = 23; } $obj = new Foo(); $refObj = new ReflectionObject( $obj ); $refProp = $refObj->getProperty( 'bar' ); echo $refProp->getValue( $obj ); ?>

PHP thanked it to you with this:

ReflectionException: Cannot access non-public member Foo::bar in /home/dotxp/dev/ez/ezcomponents/trunk/reflection.php on line 12

While it is absolutly correct that direct access to private properties is strictly forbidden, it is quite disturbing that even reflection cannot do it when you do metaprogramming where accessing private properties can be essential. Today things changed for PHP 5.3 and 6, after Derick and me managed to convince Marcus and Derick provided a patch. You still need to explicitly state that you want to access the value of a protected/private property through reflection by the new method setAccessible() (which is a good thing to avoid people doing stupid things accedentally), but you finally get the access to it:

<?php class Foo { private $bar; } $obj = new Foo(); $refObj = new ReflectionObject( $obj ); $refProp = $refObj->getProperty( 'bar' ); // Gather access to this properties value, although it is private $refProp->setAccessible( true ); echo $refProp->getValue( $obj ); ?>

This code should not throw an exception to you, but print the desired 23 value.

Thanks to Marcus and Derick for getting this finally done, so that we can soon forget about ugly hacks in the metaprogramming and testing area.

Comments

It's setAccessible(), not setAccesible().

Derick at 2008-02-15

K, fixed here, too. ;)

Toby at 2008-02-15

Does the new method return a clone of internal objects? If not, encapsulation could be broken. For example, you could return an internal private property and modify it in a way that would break the class.

Michael Gauthier at 2008-02-16

The first code snippet worked in 5.1.6--something was broken since then.

sapphirecat at 2008-02-17

No, it does not clone anything. You can't change the value though... just read it.

Derick at 2008-02-17

No, objects stored in private properties are not cloned and you are correct, that encapsulation is broken by this. This is the reason for the setAccessible() method, to ensure the developer knows, what he does.

Toby at 2008-02-17

It seems that this does not works now:

Fatal error: Call to undefined method ReflectionProperty::setAccessible()

My version: PHP 5.2.10-2ubuntu6.4 with Suhosin-Patch 0.9.7 (cli) (built: Jan 6 2010 22:41:56)

Someone knows how to do it now?

Fran at 2010-02-02

Oops! I see that you're using PHP5.3, so forget my previous comment, it's clear that the problem should be that this feature is not supported on PHP5.2 that's what I'm using.

Fran at 2010-02-02