Skip to content

Instantly share code, notes, and snippets.

@samsamm777
Last active April 26, 2024 13:24
Show Gist options
  • Save samsamm777/7230159 to your computer and use it in GitHub Desktop.
Save samsamm777/7230159 to your computer and use it in GitHub Desktop.
PHP set private property value using reflection. This allows you to set a private property value from outside the object, great for PHPUnit testing.
<?php
$a = new A();
$reflection = new \ReflectionClass($a);
$property = $reflection->getProperty('privateProperty');
$property->setAccessible(true);
$property->setValue($a, 'new-value');
echo $a->getPrivateProperty();
//outputs:
//new-value
@pgee70
Copy link

pgee70 commented Nov 26, 2018

Along similar lines, this trait will let you copy similar properties from one class to another.

trait To_trait
{
  /**
   * This snippet converts the current class into the requested class,
   * returning an instance of the requested class where the properties are equal.
   *
   * @param string $class_name
   *
   * @return mixed
   * @throws \ReflectionException
   */
  public function to (string $class_name)
  {
    if (class_exists($class_name) === FALSE)
    {
      throw new InvalidArgumentException("The class '{$class_name}' can not be found!'");
    }
    $from_reflection_object = new \ReflectionObject($this);
    $to = new $class_name;
    $reflected_class   = new \ReflectionClass($class_name);
    foreach ($from_reflection_object->getProperties() as $from_property)
    {
      $from_name = $from_property->getName();
      if ($this->$from_name === NULL)
      {
        continue;
      }
      $from_property->setAccessible(TRUE);
      foreach ($reflected_class->getProperties() as $to_property)
      {
        $to_name = $to_property->getName();
        if ($to_name !== $from_name)
        {
          continue;
        }
        $to_property->setAccessible(TRUE);
        $to_property->setValue($to,$this->$from_name);
        break;
      }
    }
    return $to;
  }
}

In your class just add:

Use To_trait;

then you can
$a = new A();
$b = $a->to('B');

@sfmok
Copy link

sfmok commented Aug 20, 2019

You can use readAttribute easier

@Amegatron
Copy link

Amegatron commented Apr 10, 2024

You can also use a closure binding:

class A {
  private string $name;
}

$a = new A();

$setter = (function (string $property, mixed $value): void {
    $this->{$property} = $value;
})->bindTo($a, $a);
$setter('name', 'Name');

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment