|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2019-10-23 16:30 UTC] 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 PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Fri Oct 24 16:00:02 2025 UTC |
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.Ok, but why is public string $bar; or protected string $bar; not set proper in the first place, regardless of the scope? Basically this is useless: public string $bar; because there seems no way to set the property in any way if an _get & _set is present. Test this class X { protected string $bar; public function __construct(){ $this->bar = 'FOO'; print $this->bar.PHP_EOL; } public function __set($name, $value) { $this->{$name} = $value; } } $obj = new X(); and it works. How strange....