Is there any way to set a private/protected static property using reflection classes?

31,366

Solution 1

For accessing private/protected properties of a class we may need to set the accessibility of that class first, using reflection. Try the following code:

$obj         = new ClassName();
$refObject   = new ReflectionObject( $obj );
$refProperty = $refObject->getProperty( 'property' );
$refProperty->setAccessible( true );
$refProperty->setValue(null, 'new value');

Solution 2

For accessing private/protected properties of a class, using reflection, without the need for a ReflectionObject instance:

For static properties:

<?php
$reflection = new \ReflectionProperty('ClassName', 'propertyName');
$reflection->setAccessible(true);
$reflection->setValue(null, 'new property value');


For non-static properties:

<?php
$instance = new SomeClassName();
$reflection = new \ReflectionProperty(get_class($instance), 'propertyName');
$reflection->setAccessible(true);
$reflection->setValue($instance, 'new property value');
Share:
31,366
dqhendricks
Author by

dqhendricks

(An unmatched left parenthesis creates an unresolved tension that will stay with you for the rest of the day.

Updated on July 09, 2021

Comments

  • dqhendricks
    dqhendricks almost 3 years

    I am trying to perform a backup/restore function for static properties of classes. I can get a list of all of the static properties and their values using the reflection objects getStaticProperties() method. This gets both private and public static properties and their values.

    The problem is I do not seem to get the same result when trying to restore the properties with the reflection objects setStaticPropertyValue($key, $value) method. private and protected variables are not visible to this method as they are to getStaticProperties(). Seems inconsistent.

    Is there any way to set a private/protected static property using reflection classes, or any other way for that matter?

    TRIED

    class Foo {
        static public $test1 = 1;
        static protected $test2 = 2;
    
        public function test () {
            echo self::$test1 . '<br>';
            echo self::$test2 . '<br><br>';
        }
    
        public function change () {
            self::$test1 = 3;
            self::$test2 = 4;
        }
    }
    
    $test = new foo();
    $test->test();
    
    // Backup
    $test2 = new ReflectionObject($test);
    $backup = $test2->getStaticProperties();
    
    $test->change();
    
    // Restore
    foreach ($backup as $key => $value) {
        $property = $test2->getProperty($key);
        $property->setAccessible(true);
        $test2->setStaticPropertyValue($key, $value);
    }
    
    $test->test();
    
  • ThorSummoner
    ThorSummoner over 9 years
    ReflectionProperty::setValue() expects parameter 1 to be object, null given, Your answer suggest I should supply a null but php complains :(
  • ThorSummoner
    ThorSummoner over 9 years
    ReflectionProperty::setValue() expects parameter 1 to be object, null given Your answer has the same problem as I had with @Shamee's
  • Michael Moussa
    Michael Moussa over 9 years
    Note that ->setValue(null, '...') is only allowed if the property being set is a static property. If you're attempting to modify an object property, you need to provide a real instance, or PHP will complain about ReflectionProperty::setValue() expects parameter 1 to be object, null given.
  • DanielM
    DanielM over 8 years
    This certainly works in PHP 5.6, and the documentation suggests this was always how it should work (see: php.net/manual/en/reflectionproperty.setvalue.php), so not sure why it didn't work for @ThorSummoner
  • TarranJones
    TarranJones about 3 years
    Great answer, Just wanted to add a note that might help someone else one day, When setting private properties you must pass the class name to which the property belongs. If the property belongs to the parent class you could do \ReflectionProperty(get_parent_class($instance), 'propertyName') otherwise you should do \ReflectionProperty(\namespace\ParentClass::class,'propertyN‌​ame') If the private property belongs to the current class then \ReflectionProperty($instance, 'propertyName')