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
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: leuffen at continue dot de
New email:
PHP Version: OS:

 

 [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

Pull Requests

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: Sat Dec 21 17:01:58 2024 UTC