Req #67830 [Nab]: PropertyReflection->setAccessible(false) not affecting public properties
| From: | leuffen at continue dot de | Date: | Thu, 14 Aug 2014 08:17:11 +0000 |
| Subject: | Req #67830 [Nab]: PropertyReflection->setAccessible(false) not affecting public properties | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-187117@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=67830&edit=1
ID: 67830
User updated by: leuffen at continue dot de
Reported by: leuffen at continue dot de
Summary: PropertyReflection->setAccessible(false) not
affecting public properties
Status: Not a bug
Type: Feature/Change Request
Package: Reflection related
Operating System: Linux
PHP Version: 5.5.15
Block user comment: N
Private report: N
New Comment:
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.
Previous Comments:
------------------------------------------------------------------------
[2014-08-14 05:13:19] levim@php.net
As specified in the comments, this is not a bug.
------------------------------------------------------------------------
[2014-08-14 04:42:18] 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 04:21:58] 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:17:26] 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-12 14:33:38] 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"
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=67830&edit=1