From: Operating system: Windows/Linux PHP version: 5.3.6 Package: Reflection related Bug Type: Feature/Change Request Bug description:Access to protected/private members using reflection
Description: ------------ Allow me to preface by saying, I am aware of bug #40348. I believe you made a mistake when, as the other reporter put it, you "corrected" that "bug" - in the following, I will attempt to explain and cite evidence from other languages, and software implemented on other platforms. The ReflectionProperty::getValue() and ReflectionProperty::setValue() methods don't work for protected and private properties - they work only for public members, which makes them redundant, since you can already use simple syntax like $object->{$propertyName} to access public members. The ReflectionMethod::invoke() method also does not work for protected and private methods - again, this only works for public members, which you can already invoke in other ways, making this method redundant. I believe the idea behind reflection, is to enable the implementation of popular meta-programming patterns. In order to do this, the language provides access to things that your programs would otherwise have no knowledge of, such as property-types, argument lists, etc. Another important aspect of property and method reflection, is to facilitate access to protected and private members. While the reflection-classes will enable you to find protected and private members, the current implementation leaves your program with the knowledge of these members, but being unable to perform any operations on them. This awareness of the internals of a class, unfortunately, is useless - there is no meaningful operation you can perform based on this information. The idea of allowing access to protected/private members, may seem counter-intuitive at first, but it is necessary. With reflection, you provided access to information that was "private" to the internal interpretation of the source-code by the programming language itself. In much the same way, and for the same reasons, you need to provide access to private members of user code. While, theoretically, you could write terrible, incomprehensible code, by giving yourself read/write access to any property of any object, this is of course not why this feature exists in other languages - it exists to facilitate good, clean meta-programming. An object-relational mapper, for example, would likely need access to protected and private members, in order to persist them to the database. In programming languages like C# and Java, this is possible, and enables (for example) Hibernate (and NHibernate on .NET) to persist protected and private members to the database. Another example is debugging and diagnostic components, which would likely need access to protected and private members - and preferably not by contrived means, such as are necessary at the moment. To cite precedence, the following unit test passes in C#: class Foo { public Foo() { Bar = 123; } private int Bar { get; set; } } [Test] public void CanAccessPrivateMembers() { var test = new Foo(); // test.Bar = 456; // this is private and inaccessible var property = test.GetType().GetProperty("Bar", BindingFlags.Instance | BindingFlags.NonPublic); Assert.AreEqual(123, property.GetValue(test, null), "access to private member Foo.Bar"); } By using reflection to access private members, the programmer enters into an agreement - he should have the understanding that things can wrong when this feature is not used responsibly. Documentation for this feature should be clear about the fact that access to private members is only typically useful for meta-programming. For example, when you are enumerating the properties of an object, and making decisions based on other available metadata. Documentation should clarify that this feature should not be "abused" as a means to forcibly get access to a specific member, since that would defeat the purpose of having protected/private members in the first place. In conclusion, the removal of this feature was a mistake - reflection in PHP is currently crippled, and not as useful as it is in other languages. Test script: --------------- <?php class Foo { protected $bar = 123; protected function hello() { echo 'Hello, World'; } } $object = new Foo; var_dump($object); $property = new ReflectionProperty('Foo', 'bar'); # var_dump($property->getValue($object)); // doesn't work $method = new ReflectionMethod('Foo', 'hello'); # $method->invoke($object); // doesn't work Expected result: ---------------- Both of the commented-out lines would cause the script to fail. Uncommenting the first line, which should print '123', causes an exception. Uncommenting the second line, should print 'Hello, World', but causes an exception. Not demonstrated in this script is ReflectionProperty::setValue() which should also work. Actual result: -------------- Exceptions as described above. -- Edit bug report at http://bugs.php.net/bug.php?id=55026&edit=1 -- Try a snapshot (PHP 5.2): http://bugs.php.net/fix.php?id=55026&r=trysnapshot52 Try a snapshot (PHP 5.3): http://bugs.php.net/fix.php?id=55026&r=trysnapshot53 Try a snapshot (trunk): http://bugs.php.net/fix.php?id=55026&r=trysnapshottrunk Fixed in SVN: http://bugs.php.net/fix.php?id=55026&r=fixed Fixed in SVN and need be documented: http://bugs.php.net/fix.php?id=55026&r=needdocs Fixed in release: http://bugs.php.net/fix.php?id=55026&r=alreadyfixed Need backtrace: http://bugs.php.net/fix.php?id=55026&r=needtrace Need Reproduce Script: http://bugs.php.net/fix.php?id=55026&r=needscript Try newer version: http://bugs.php.net/fix.php?id=55026&r=oldversion Not developer issue: http://bugs.php.net/fix.php?id=55026&r=support Expected behavior: http://bugs.php.net/fix.php?id=55026&r=notwrong Not enough info: http://bugs.php.net/fix.php?id=55026&r=notenoughinfo Submitted twice: http://bugs.php.net/fix.php?id=55026&r=submittedtwice register_globals: http://bugs.php.net/fix.php?id=55026&r=globals PHP 4 support discontinued: http://bugs.php.net/fix.php?id=55026&r=php4 Daylight Savings: http://bugs.php.net/fix.php?id=55026&r=dst IIS Stability: http://bugs.php.net/fix.php?id=55026&r=isapi Install GNU Sed: http://bugs.php.net/fix.php?id=55026&r=gnused Floating point limitations: http://bugs.php.net/fix.php?id=55026&r=float No Zend Extensions: http://bugs.php.net/fix.php?id=55026&r=nozend MySQL Configuration Error: http://bugs.php.net/fix.php?id=55026&r=mysqlcfg