mwieczorek
mwieczorek

Reputation: 2252

Cannot set read-only property ReflectionObject

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

Answers (1)

thehennyy
thehennyy

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 );

https://3v4l.org/ZdK27

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

Related Questions