Bug #78744 [Opn]: Unexpected __set & __get behavior
| From: | nikic@php.net | Date: | Wed, 23 Oct 2019 16:46:14 +0000 |
| Subject: | Bug #78744 [Opn]: Unexpected __set & __get behavior | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-223422@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=78744&edit=1
ID: 78744
Updated by: nikic@php.net
Reported by: dirk dot gerigk at tui dot com
Summary: Unexpected __set & __get behavior
Status: Open
Type: Bug
Package: Class/Object related
Operating System: Linux
PHP Version: 7.4.0RC4
Block user comment: N
Private report: N
New Comment:
The __get() result value must still satisfy the property type if it is invoked on a visible, but
unset/uninitialized property. Otherwise it would be possible to bypass the property type this way.
It should be noted that something like this will not throw an error:
<?php
class X
{
protected string $bar;
protected array $array = [];
public function __set($name, $value)
{
print "set $name = $value".PHP_EOL; $this->array[$name] =
$value;
}
public function __get($name)
{
print 'get '.$name.PHP_EOL; return $this->array[$name] ?? null;
}
}
$obj = new X();
$obj->bar = 'FOO'; print $obj->bar.PHP_EOL;
The reason is that here the access is performed from a scope where the property is not visible, so
the type doesn't apply either. The type only applies if it is visible.
See also https://wiki.php.net/rfc/typed_properties_v2#overloaded_properties.
Previous Comments:
------------------------------------------------------------------------
[2019-10-23 16:30:34] dirk dot gerigk at tui dot com
Description:
------------
Issue is that __get and __set does some strange things
when commenting in and out the $this->array = []; line.
Test the code and you will see.
This all started with "Typed Properties" and its is very strange.
So, is this normal behavior? If yes, why is that so?
Must Important Question:
Why are the magic methods connected to the property definition and the error clearly says
"X::$bar must be string, null used"? Because at this point the __get returns NULL.
On a previous BUG Report (Bug #78226) someone sayed: Do always ?string $foo = null;
But that can be the solution to this, or?
Test script:
---------------
class X
{
protected string $bar;
protected array $array = [];
public function __construct(string $bar)
{
$this->bar = $bar; $this->array = []; print $this->bar.PHP_EOL;
}
public function __set($name, $value)
{
print "set $name = $value".PHP_EOL; $this->array[$name] = $value;
}
public function __get($name)
{
print 'get '.$name.PHP_EOL; return $this->array[$name] ?? null;
}
}
$obj = new X('FOO');
Expected result:
----------------
set bar = FOO
get bar
FOO
Actual result:
--------------
set bar = FOO
get bar
Fatal error: Uncaught TypeError: Typed property X::$bar must be string, null used
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=78744&edit=1