php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #78226 Unexpected __set behavior with typed properties
Submitted: 2019-06-28 10:26 UTC Modified: 2019-08-18 13:26 UTC
Votes:3
Avg. Score:4.7 ± 0.5
Reproduced:3 of 3 (100.0%)
Same Version:3 (100.0%)
Same OS:3 (100.0%)
From: dirk dot gerigk at tui dot com Assigned: nikic (profile)
Status: Closed Package: Class/Object related
PHP Version: 7.4Git-2019-06-28 (Git) 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: dirk dot gerigk at tui dot com
New email:
PHP Version: OS:

 

 [2019-06-28 10:26 UTC] dirk dot gerigk at tui dot com
Description:
------------
Maybe it is a not implemented yet in alpha1, 
but i found a unexpected behavior when using __set / __get.
I will only point to one issue i found. 

So, when you use __set in a class and typ-hint a property, 
the __set method is always called.


Side Note (other issue):
Is it normal that you have to make every type-hinted property nullable?
Because when you have: public string $bar; 
And do: (new A)->bar;
You get: Fatal error: Uncaught TypeError: Typed property A::$bar must be string, null used

Is that wanted in that way? 

Test script:
---------------
class A {
    public string $bar;
    public $foo;
    final public function __get($name){
        print "get_$name ";
    }
    final public function __set($name,$arg){
        print "set_$name ";
    }
}
$obj = new A;
$obj->bar='';
$obj->foo='';
var_export($obj);

Expected result:
----------------
A::__set_state(array( 'bar' => '', 'foo' => '', ))

Actual result:
--------------
set_bar A::__set_state(array( 'foo' => '', ))

Patches

Pull Requests

Pull requests:

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2019-06-28 10:43 UTC] dirk dot gerigk at tui dot com
OK, forget the side note. i have read this https://wiki.php.net/rfc/typed_properties_v2 and it is explained there.
 [2019-06-28 11:02 UTC] nikic@php.net
This is working "as intended", though I agree that the behavior is quite surprising. Typed properties start out uninitialized/unset and accessing unset properties causes calls to __get/__set.

If you can, don't use __set. If you can't, use

    public ?string $bar = null;

to explicitly initialize it the property to null, though you will have to deal with the consequences of that.

It would be nice to have a way to bypass __set when assigning to an unset property (including uninitialized typed properties), but I don't see any obvious way to support that.
 [2019-06-28 15:13 UTC] dirk dot gerigk at atraveo dot com
Thanx for the fast answer.
I have taken the time to read the https://wiki.php.net/rfc/typed_properties_v2 in detail and was suprised how complex the hole thing will be.
I think will dig into it fully (writing code), when it is implement full in the future.

But i am still curious how it will work in the future, so is there a link to a final draft of the implementation?
 [2019-06-28 15:23 UTC] dirk dot gerigk at atraveo dot com
Ignore my last question in the last comment. :-)
 [2019-07-23 07:08 UTC] wanghao at imwh dot net
The behavior is quite surprising.It make me upset.
 [2019-08-13 20:51 UTC] nikic@php.net
-Summary: Unexpected __set behavior +Summary: Unexpected __set behavior with typed properties
 [2019-08-14 12:47 UTC] tandrewbennett at hotmail dot com
For what it's worth, I think that a lot of the use cases for using __set() in userland code are based on devs trying to roll their own property accessor syntax for their entities, value objects, etc. I think this new behavior would be a non issue if we had something like this: https://wiki.php.net/rfc/propertygetsetsyntax-v1.2

I know there are differing opinions regarding the specific syntax (some prefer a C# style syntax while other prefer an ES6 based approach), but I still think it's worth mentioning here, perhaps for future releases.
 [2019-08-18 13:26 UTC] nikic@php.net
-Status: Open +Status: Assigned -Assigned To: +Assigned To: nikic
 [2019-08-18 13:26 UTC] nikic@php.net
I think we'll have to change the semantics of __set to not be called for properties that are declared but unset (or uninitialized).
 [2019-09-11 09:54 UTC] nikic@php.net
The following pull request has been associated:

Patch Name: Don't invoke __set() on accessible declared but unset properties
On GitHub:  https://github.com/php/php-src/pull/4696
Patch:      https://github.com/php/php-src/pull/4696.patch
 [2019-10-24 10:02 UTC] nikic@php.net
The following pull request has been associated:

Patch Name: Don't call __set() on uninitialized typed properties
On GitHub:  https://github.com/php/php-src/pull/4854
Patch:      https://github.com/php/php-src/pull/4854.patch
 [2019-10-25 14:32 UTC] nikic@php.net
Automatic comment on behalf of nikita.ppv@gmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=f1848a4b3f807d21415c5a334b461d240b2a83af
Log: Fix bug #78226: Don't call __set() on uninitialized typed properties
 [2019-10-25 14:32 UTC] nikic@php.net
-Status: Assigned +Status: Closed
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sun Oct 27 16:01:27 2024 UTC