Edit report at https://bugs.php.net/bug.php?id=64497&edit=1

 ID:                 64497
 User updated by:    me at fixxxer dot me
 Reported by:        me at fixxxer dot me
 Summary:            ReflectionProperty::setValue triggers __set for
                     unset property
 Status:             Open
 Type:               Bug
 Package:            Reflection related
 Operating System:   any
 PHP Version:        5.4Git-2013-03-23 (snap)
 Block user comment: N
 Private report:     N

 New Comment:

Some more thoughts on this issue.

Existence of unset() property is weird by itself.

I do understand why unset properties aren't completely removed from an object: 
it's required to preserve the visibility scope. But it believe it should be 
completely hidden from "outer world", and should not be exposed to 
property_exists, Reflection or whatever.


Previous Comments:
------------------------------------------------------------------------
[2013-03-23 22:45:41] me at fixxxer dot me

Description:
------------
I'm not sure it's a bug. And if it is, it's a low priority bug.

But current behavior is illogical: ReflectionProperty represents an existing 
property, and it is logical to assume it never triggers magic methods.

The case is a bit weird. :) We've had a discussion on phpclub.ru forums (in 
Russian, http://phpclub.ru/talk/threads/75432/page-2) about dealing with the 
case when a property has been unset() and there are magic methods present.

When you unset a property, it is visible as undefined ("Undefined property" 
notice), and if there is a __set method, it starts being triggered when setting 
te same property. But property_exists() returns true for this property, so it 
means the property is still there in internal object structures - it is not the 
same as it has never been defined. During the discussion on restoring the 
property without triggering __set, I came up with an idea to use 
ReflectionProperty. But it ended up with a strange result shown in the test 
script.

My point is that ReflectionProperty::setValue should never trigger __set.

Test script:
---------------
class C {

    protected $foo;

    public function test() {
        var_dump('Setting value with ReflectionProperty::setValue...');
        $foo = (new ReflectionClass($this))->getProperty('foo');
        $foo->setAccessible(true);
        $foo->setValue($this, 'foo'); // sets value, ok
        $foo->setAccessible(false);

        var_dump($this->foo);

        var_dump('Unsetting...');
        unset($this->foo);
        var_dump($this->foo);

        var_dump('Setting value with ReflectionProperty::setValue again...');
        $foo = (new ReflectionClass($this))->getProperty('foo');
        $foo->setAccessible(true);
        $foo->setValue($this, 'foo'); // triggers __set() !
        $foo->setAccessible(false);

        var_dump($this->foo);
    }

    public function __set($k, $v) {
        var_dump("__set triggered: [$k] = '$v'");
    }

}

(new C)->test();

Expected result:
----------------
string(50) "Setting value with ReflectionProperty::setValue..."
string(3) "foo"
string(12) "Unsetting..."

Notice: Undefined property: C::$foo in /home/build/tmp/1.php on line 20
NULL
string(56) "Setting value with ReflectionProperty::setValue again..."
string(3) "foo"


Actual result:
--------------
string(50) "Setting value with ReflectionProperty::setValue..."
string(3) "foo"
string(12) "Unsetting..."

Notice: Undefined property: C::$foo in /home/build/tmp/1.php on line 20
NULL
string(56) "Setting value with ReflectionProperty::setValue again..."
string(30) "__set triggered: [foo] = 'foo'"

Notice: Undefined property: C::$foo in /home/build/tmp/1.php on line 28
NULL


------------------------------------------------------------------------



-- 
Edit this bug report at https://bugs.php.net/bug.php?id=64497&edit=1

Reply via email to