php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #78372 Calling __set magic method on ReflectionProperty::setValue()
Submitted: 2019-08-05 07:10 UTC Modified: 2019-08-05 09:18 UTC
From: i dot spyric at gmail dot com Assigned:
Status: Duplicate Package: Scripting Engine problem
PHP Version: 7.4.0beta1 OS: Debian
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: i dot spyric at gmail dot com
New email:
PHP Version: OS:

 

 [2019-08-05 07:10 UTC] i dot spyric at gmail dot com
Description:
------------
When you use setting value via reflection on uninitialized property __set magic method will be called. 

If you remove type of property or set default value, __set method will not be called.

Is it a bug? Because in RFC I have not seen anything about this behavior

Test script:
---------------
class Example {
    private string $test;

    public function __set($name, $value)
    {
        echo "$name=$value";
    }
}

$t = new Example();

$property = new ReflectionProperty($t, 'test');
$property->setAccessible(true);
$property->setValue($t, 'foo');

Expected result:
----------------
No __set is called

Actual result:
--------------
__set is called

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2019-08-05 07:20 UTC] requinix@php.net
-Status: Open +Status: Not a bug
 [2019-08-05 07:20 UTC] requinix@php.net
The RFC states that __get will be invoked upon reading an uninitialized typed property. Logically, __set should be invoked when writing an uninitialized typed property.

This behavior matches how an unset() untyped property works, even when using reflection. https://3v4l.org/Gs1XL
 [2019-08-05 07:55 UTC] nikic@php.net
While this is technically "expected", I do think that we may need to do something about this, though I'm not sure what. See also bug #78226.
 [2019-08-05 08:50 UTC] requinix@php.net
-Status: Not a bug +Status: Duplicate
 [2019-08-05 08:50 UTC] requinix@php.net
Then really this is a duplicate: the typed properties + __set problem, this time using reflection.

The awkwardness is specifically about the property being uninitialized; once set, or when specifically unset(), __get/etc. act as expected. So it's looking like a class cannot effectively use uninitialized typed properties as well as __get/etc, and that the best option will be to always initialize them with something - even if 0 or "" or false. (I myself already do this with untyped properties.)

In fact this feels like it'll be such a surprise that I would say maybe typed properties *must* be initialized, in the declaration itself:
  private string $test = "";
I don't see this option mentioned in the RFC and I don't remember if it came up during the RFC discussion. Rationale is that every property should always end up either with some real value or as null to represent a lack of value; for the former this default won't make much of a difference since it will be overwritten, and for the latter the type should have been ?nullable and so could be implicitly initialized by PHP (to null).
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sun Nov 24 07:02:12 2024 UTC