[php-src] Issue #22441: ReflectionClass issues with dynamic properties shadowing private parent properties
[email protected] (DanielEScherzer) Wed, 24 Jun 2026 17:01:43 +0000
| Newsgroups | php.bugs |
|---|---|
| Message-ID | <[email protected]> |
Issue: https://github.com/php/php-src/issues/22441
Author: DanielEScherzer
### Description
The following code:
```php
<?php
class Base {
private mixed $shadow;
}
#[AllowDynamicProperties]
class Child extends Base {}
$o = new Child();
$o->shadow = true;
$o->noShadow = true;
var_dump($o);
echo "\n";
$r = new ReflectionObject($o);
echo "hasProperty():\n";
var_dump($r->hasProperty('shadow'));
var_dump($r->hasProperty('noShadow'));
echo "\n";
echo "getProperties():\n";
try {
var_dump($r->getProperty('shadow'));
} catch (\Throwable $e) {
echo $e->getMessage(). "\n";
}
echo "\n";
var_dump($r->getProperty('noShadow'));
echo "\n";
echo "getProperties():\n";
var_dump($r->getProperties());
```
Resulted in this output:
```
object(Child)#1 (2) {
["shadow":"Base":private]=>
uninitialized(mixed)
["shadow"]=>
bool(true)
["noShadow"]=>
bool(true)
}
hasProperty():
bool(false)
bool(true)
getProperties():
Property Child::$shadow does not exist
object(ReflectionProperty)#4 (2) {
["name"]=>
string(8) "noShadow"
["class"]=>
string(5) "Child"
}
getProperties():
array(2) {
[0]=>
object(ReflectionProperty)#4 (2) {
["name"]=>
string(6) "shadow"
["class"]=>
string(5) "Child"
}
[1]=>
object(ReflectionProperty)#5 (2) {
["name"]=>
string(8) "noShadow"
["class"]=>
string(5) "Child"
}
}
```
But I expected this output instead:
```
object(Child)#1 (2) {
["shadow":"Base":private]=>
uninitialized(mixed)
["shadow"]=>
bool(true)
["noShadow"]=>
bool(true)
}
hasProperty():
bool(true)
bool(true)
getProperties():
object(ReflectionProperty)#4 (2) {
["name"]=>
string(8) "shadow"
["class"]=>
string(5) "Child"
}
object(ReflectionProperty)#5 (2) {
["name"]=>
string(8) "noShadow"
["class"]=>
string(5) "Child"
}
getProperties():
array(2) {
[0]=>
object(ReflectionProperty)#4 (2) {
["name"]=>
string(6) "shadow"
["class"]=>
string(5) "Child"
}
[1]=>
object(ReflectionProperty)#5 (2) {
["name"]=>
string(8) "noShadow"
["class"]=>
string(5) "Child"
}
}
```
ReflectionClass::hasProperties() and ::getProperties() only check dynamic properties after checking for a matching property of the same name that could be a private parent property
### PHP Version
```plain
8.4+
```
### Operating System
_No response_