schlitt.info - php, photography and private stuff ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :Author: Tobias Schlitt :Date: Wed, 19 Nov 2008 23:29:46 +0100 :Revision: 1 :Copyright: CC by-nc-sa ============================= Reflecting private properties ============================= :Description: 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: 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: .. __: http://php.net/manual/en/language.oop5.reflection.php#language.oop5.reflection.reflectionproperty :: 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: .. __: http://en.wikipedia.org/wiki/Metaprogramming .. __: http://derickrethans.nl .. __: http://blog.somabo.de/ .. __: http://php.net/reflection :: 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. .. __: http://blog.somabo.de/ .. __: http://derickrethans.nl .. __: http://derickrethans.nl/private_properties_exposed.php .. Local Variables: mode: rst fill-column: 79 End: vim: et syn=rst tw=79 Trackbacks ========== - Tobias Schlitt's Blog: Reflecting private properties on Fri, 15 Feb 2008 15:48:54 +0100 in PHPDeveloper.org Tobias Schlitt has posted a handy tip about using the Reflection ... - Accessing private properties in Unit Tests on Thu, 13 Mar 2008 19:23:33 +0100 in Blog of Max Horvath While it's absolutly correct that direct access to private properties is strictly forbidden in PHP, it's quite disturbing that even reflection cannot do it when you're writing Unit Tests. Sometimes you just want to test whether a private property contains... Comments ======== - Derick at Fri, 15 Feb 2008 14:11:19 +0100 It's setAccessible(), not setAccesible(). - Toby at Fri, 15 Feb 2008 14:34:58 +0100 K, fixed here, too. ;) - Michael Gauthier at Sat, 16 Feb 2008 20:44:14 +0100 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. - sapphirecat at Sun, 17 Feb 2008 14:09:58 +0100 The first code snippet worked in 5.1.6--something was broken since then. - Derick at Sun, 17 Feb 2008 17:18:09 +0100 No, it does not clone anything. You can't change the value though... just read it. - Toby at Sun, 17 Feb 2008 17:19:14 +0100 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. - Fran at Tue, 02 Feb 2010 18:07:21 +0100 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 Tue, 02 Feb 2010 18:20:44 +0100 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. - Ahmad Al Jayousi at Tue, 23 Nov 2010 14:36:07 +0100 Ahmad Al Jayousi Philadelphia University Jordan http://www.philadelphia.edu.jo E-mail: aaljayousi@philadelphia.edu.jo - Lu4 at Tue, 11 Jan 2011 00:56:57 +0100 I think that using setAccessible(true) is a rubbish, when people are using reflection aren't they already aware of what are they doing? - Lu4 at Tue, 11 Jan 2011 01:07:49 +0100 Reflection is good for delegates implementation, not just call_user_func function that calls public class members but, the real delegates to private class members. Things like Events and EventHandlers can not be implemented without delegates and blocking this feature makes php lack huge class of OOP patterns that are common to other languages. Check http://stackoverflow.com/questions/4584182/the-correct-way-of-doing-delegates-or-callbacks-in-php - Adrian at Fri, 13 Jan 2012 10:26:09 +0100 Hi have, principally, the same approach but more bound to the concern, imho: setAccessible(true); echo $reflectedProperty->getValue($instanciatedClass); ?> I write this here because it took myself a bit to get the approach of the reflection; the idea is with ->getValue get the value of the reflected property *in context* to the object passed in as parameter.