Reputation: 2252
I'm having difficulty writing to class properties using the Reflection API. $p->setValue($r, $value)
throws an exception saying that the property is read only, however, PHP (to my knowledge) has no read only class properties (only methods using final
), so what's the crack here?
The problem code:
public function apply($source, $target) {
$r = new \ReflectionObject($target);
foreach ($source as $key => $value) {
// $this->entries[$key] maps to a valid property of $target. Confirmed working
$p = $r->getProperty($this->entries[$key]);
$p->setAccessible(true);
$p->setValue($r, $value); // <--- problem here
}
}
The exception reads as follows:
Uncaught ReflectionException: Cannot set read-only property ReflectionObject::$name
An excerpt from the class being reflected ($target
in the above snippet), this issue remains whether I set the properties to public
or keep private
class Target {
private $id;
private $name;
}
Nothing special going on with this class, just a plain object with a default constructor.
Is there something in the docs that I've missed, or is this just PHP weirdness that I need to accept?
Using version 7.1, but note that I haven't worked with PHP for over a decade (thankfully), so I may not be aware of obvious developments.
Upvotes: 1
Views: 795
Reputation: 4218
You have to pass the instance you want to set the property on as the first argument in the setValue()
call.
Have a look at this example:
<?php
class A
{
private $name = 'ABC';
}
$obj = new A();
$r = new ReflectionObject( $obj );
$prop = $r->getProperty( 'name' );
$prop->setAccessible( true );
$prop->setValue( $obj, 'DEF' );
var_dump( $obj );
The output is:
object(A)#1 (1) { ["name":"A":private]=> string(3) "DEF" }
Currently you try to set the property of the ReflectionObject
instance, that coincidentally has a property with the same name. But this is not allowed by the runtime as it probably would break the reflection setup.
Upvotes: 1