Closed
Description
Description
The following code: https://3v4l.org/Zbnqa
<?php
class ParentClass
{
protected readonly int $value;
}
trait Foo
{
protected readonly int $value;
}
class ChildClassWithoutTrait extends ParentClass
{
protected readonly int $value;
}
$reflector = new ReflectionClass(ChildClassWithoutTrait::class);
$instance = $reflector->newInstanceWithoutConstructor();
var_dump(
$reflector->hasProperty('value'),
$prop = $reflector->getProperty('value')
);
$prop->setValue($instance, 20);
var_dump($instance);
echo '--------------------------------------------------------------------------------------------------------', PHP_EOL;
class ClassWithTraitAndNoParent
{
use Foo;
}
$reflector = new ReflectionClass(ClassWithTraitAndNoParent::class);
$instance = $reflector->newInstanceWithoutConstructor();
var_dump(
$reflector->hasProperty('value'),
$prop = $reflector->getProperty('value')
);
$prop->setValue($instance, 20);
var_dump($instance);
echo '--------------------------------------------------------------------------------------------------------', PHP_EOL;
class ChildClassWithTrait extends ParentClass
{
use Foo;
}
$reflector = new ReflectionClass(ChildClassWithTrait::class);
$instance = $reflector->newInstanceWithoutConstructor();
var_dump(
$reflector->hasProperty('value'),
$prop = $reflector->getProperty('value')
);
$prop->setValue($instance, 20);
var_dump($instance);
Resulted in this output:
bool(true)
object(ReflectionProperty)#3 (2) {
["name"]=>
string(5) "value"
["class"]=>
string(22) "ChildClassWithoutTrait"
}
object(ChildClassWithoutTrait)#2 (1) {
["value":protected]=>
int(20)
}
--------------------------------------------------------------------------------------------------------
bool(true)
object(ReflectionProperty)#2 (2) {
["name"]=>
string(5) "value"
["class"]=>
string(25) "ClassWithTraitAndNoParent"
}
object(ClassWithTraitAndNoParent)#1 (1) {
["value":protected]=>
int(20)
}
--------------------------------------------------------------------------------------------------------
bool(true)
object(ReflectionProperty)#1 (2) {
["name"]=>
string(5) "value"
["class"]=>
string(11) "ParentClass"
}
Fatal error: Uncaught Error: Cannot initialize readonly property ParentClass::$value from scope ChildClassWithTrait in /in/Zbnqa:64
Stack trace:
#0 /in/Zbnqa(64): ReflectionProperty->setValue(Object(ChildClassWithTrait), 20)
#1 {main}
thrown in /in/Zbnqa on line 64
Process exited with code 255.
But I expected this output instead:
bool(true)
object(ReflectionProperty)#3 (2) {
["name"]=>
string(5) "value"
["class"]=>
string(22) "ChildClassWithoutTrait"
}
object(ChildClassWithoutTrait)#2 (1) {
["value":protected]=>
int(20)
}
--------------------------------------------------------------------------------------------------------
bool(true)
object(ReflectionProperty)#2 (2) {
["name"]=>
string(5) "value"
["class"]=>
string(25) "ClassWithTraitAndNoParent"
}
object(ClassWithTraitAndNoParent)#1 (1) {
["value":protected]=>
int(20)
}
--------------------------------------------------------------------------------------------------------
bool(true)
object(ReflectionProperty)#1 (2) {
["name"]=>
string(5) "value"
["class"]=>
string(11) "ChildClassWithTrait"
}
object(ChildClassWithTrait)#n (1) {
["value":protected]=>
int(20)
}
It seems that a combination of traits and inheritance somehow breaks the getProperty()
method. Even though the hasProperty()
method returns true
for ChildClassWithTrait
, the getProperty()
method returns a ReflectionProperty
for ParentClass
.
PHP Version
all
Operating System
No response