php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #67830 PropertyReflection->setAccessible(false) not affecting public properties
Submitted: 2014-08-12 14:33 UTC Modified: 2014-08-14 08:17 UTC
From: leuffen at continue dot de Assigned:
Status: Not a bug Package: Reflection related
PHP Version: 5.5.15 OS: Linux
Private report: No CVE-ID: None
View Add Comment Developer Edit
Anyone can comment on a bug. Have a simpler test case? Does it work for you on a different platform? Let us know!
Just going to say 'Me too!'? Don't clutter the database with that please !
Your email address:
MUST BE VALID
Solve the problem:
38 + 47 = ?
Subscribe to this entry?

 
 [2014-08-12 14:33 UTC] leuffen at continue dot de
Description:
------------
At present ReflectionProperty::setAccessible()  works only one-way: Changing unaccessible Properties to accessible. setAccessible(false) will have no affect. This is complicated for frameworks using __get() and __set():


Our frameworks use the magic __get() and __set() methods to validate data or to load Entities from Database.

To take advantage from common IDE's code-completion we declare these properties public and unset them whithin the constructor (and store the actual data whithin a private or protected property).

It would be a great advantage for working with these Objects if we could use the ReflectionProperty::setAccessible() Method to change property visibility to private and enforce use of __get() and __set() methods.



Test script:
---------------
class Entity {

    public $name = "direct access";

    public function __construct() {
        $ref = new ReflectionObject($this);
        foreach ($ref->getProperties() as $prop) {
            $prop->setAccessible(FALSE);
        }
    }

    public function __get($name) {
        return "access over __get()";
    }
}

$o = new Entity();
echo $o->name;

Expected result:
----------------
"access over __get()"

Actual result:
--------------
"direct access"

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2014-08-14 04:17 UTC] levim@php.net
As a general PHP user I am shocked that you use it like this. Clearly abuse in my opinion.

From a dev perspective, it probably should be supported if we claim it is supported in documentation. If not, it's just a bad API and we should change the API.
 [2014-08-14 04:21 UTC] levim@php.net
After looking into it more, this doesn't seem to be a bug. Only the property in the reflection object becomes accessible; it doesn't modify the `$this` instance. Can someone more knowledgeable in reflection review this?
 [2014-08-14 04:42 UTC] datibbaw@php.net
First of all, that's a horrendous way of doing things. You can accomplish this quite easily by using the @property DocBlock:

/**
 * Class Entity
 *
 * @property string $name
 */

That said, ReflectionProperty::setAccessible(bool) only affects calls to ReflectionProperty::get/setValue(), it doesn't actually change anything in the target object.
 [2014-08-14 05:13 UTC] levim@php.net
-Status: Open +Status: Not a bug
 [2014-08-14 05:13 UTC] levim@php.net
As specified in the comments, this is not a bug.
 [2014-08-14 08:17 UTC] leuffen at continue dot de
I don't see why this should be a bad thing to do. (Maybe defining properties in DocBlock @property is a much better way than unsetting them. But that's not the point)

The point is that although if we would, we have to store the actual data in an data-structure that differs from the IDEs point of view. So debugging etc. is much more complicated than it could be.

--testscript-
/**
 * Class Entity
 *
 * @property string $name
 */
class Entity {


    public function __construct() {
    }

    public function __set($name, $val) {
        echo "setting $name ";
        $this->$name = $val;
        $ref = new ReflectionObject($this);
        $ref->getProperty($name)->setAccessible(FALSE);
    }

    public function __get($name) {
        echo "getting $name";
    }
}

$entity = new Entity();
$entity->name = "value";
echo $entity->name;
--/testscript-

Above example will call __get() once - and afterwards access the property direcly.

If you have an better approach - please write me.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Mar 28 12:01:27 2024 UTC