Is there any way, using reflection or otherwise, to change a readonly property that has already been set?
We sometimes do that in tests, and we don't want to avoid using readonly props just for testing purposes.
class Acme {
public function __construct(
private readonly int $changeMe,
) {}
}
$object= new Acme(1);
$reflectionClass = new ReflectionClass($object);
$reflectionProperty = $reflectionClass->getProperty('changeMe');
$reflectionProperty->setAccessible(true);
$reflectionProperty->setValue($object, 2);
Fatal error: Uncaught Error: Cannot modify readonly property Acme::$changeMe
The only way I can think of to change a readonly property is to reflect the object without calling its constructor. However, not sure if it's useful in your particular case
class Acme {
public function __construct(
public readonly int $changeMe,
) {}
}
$object = new Acme(1);
$reflection = new ReflectionClass($object);
$instance = $reflection->newInstanceWithoutConstructor();
$reflectionProperty = $reflection->getProperty('changeMe');
$reflectionProperty->setValue($instance, 33);
var_dump($reflectionProperty->getValue($instance)); // 33
Note: we are not actually "changing" the property we are just setting it for the first time since no constructor is called.