3

I have a class that extends of another one.

Class Test

    class Test
    {
      private $id;
      private $name;
      private $age;
      private $number;

      public function getId() {
        return $this->id;
      }

      public function setId($id) {
         $this->id = $id;
         return $this;
      }

      public function getName() {
        return $this->name;
      }

      public function setName($name) {
         $this->name = $name;
         return $this;
      }

      public function getAge() {
        return $this->age;
      }

      public function setAge($age) {
         $this->age = $age;
         return $this;
      }

     public function getNumber() {
        return $this->number;
      }

   public function setNumber($number) {
         $this->number = $number;
         return $this;
      }
    }

Class TestCopy

use Test;  

class TestCopy extends Text
{
}

And then I have an object of the class Test:

$object = new Test();
$object->setId = 1;
$object->setName = Tom;
$object->setAge = 20;
$object->setNumber = 10;

How I can create an object of the class TestCopy (that will have the same attributes), and clone all the values of the object $object?

I tried with clone:

$objectCopy = clone $object;

But the object $objectCopy have to instance the class TestCopy, and when I clone, it instance the class Test.

And I tried so too:

foreach (get_object_vars($object) as $key => $name) {
        $objectCopy->$key = $name;
}

But the attributes are private and when I call the function get_object_vars it returns null. Any idea? Thank very much!

David
  • 45
  • 6
  • Possible duplicate of [Cast the current object ($this) to a descendent class](https://stackoverflow.com/questions/4080217/cast-the-current-object-this-to-a-descendent-class) – Nagarjun Aug 25 '17 at 14:39
  • You should create an object of the correct type in the first place, this is breaking the idea of what an object hierarchy is all about, fudging the types is just that! – Nigel Ren Aug 25 '17 at 14:45
  • Most likely you are not trying to create your own mocking framework or some inspecting tool, but a dirty hack instead. If you tell more about the whole task, we might be able to correct your approach and give you better answers. – svgrafov Aug 25 '17 at 15:17

1 Answers1

2

try this, Once you instantiate a object, you can't change the class (or other implementation details)

You can simulate it like so:

<?php

  class Test
  {
      private $id;
      private $name;
      private $age;
      private $number;

      public function getId() {
         return $this->id;
      }

      public function setId($id) {
         $this->id = $id;
         return $this;
      }

      public function getName() {
        return $this->name;
      }

      public function setName($name) {
         $this->name = $name;
         return $this;
      }

      public function getAge() {
        return $this->age;
      }

      public function setAge($age) {
         $this->age = $age;
         return $this;
      }

      public function getNumber() {
        return $this->number;
      }

      public function setNumber($number) {
         $this->number = $number;
         return $this;
      }

      public function toArray()
      {
         return get_object_vars($this);
      }

  }

  class TestCopy extends Test
  {
      public $fakeAttribute;
  }

  function getTestCopy($object)
  {
    $copy = new TestCopy();

    foreach($object->toArray() as $key => $value) {
       if(method_exists($copy, 'set'.ucfirst($key))) {
          $copy->{'set'.ucfirst($key)}($value);
       }
    }

    return $copy;
  }

$object = new Test();
$object->setId(1);
$object->setName('Tom');
$object->setAge(20);
$object->setNumber(10);

$copy = getTestCopy($object);
$copy->fakeAttribute = 'fake value';

echo "<pre>";
print_r($object->toArray());
print_r($copy->toArray());

output :

Array
(
    [id] => 1
    [name] => Tom
    [age] => 20
    [number] => 10
)
Array
(
    [fakeAttribute] => fake value
    [id] => 1
    [name] => Tom
    [age] => 20
    [number] => 10
)
yoeunes
  • 2,927
  • 2
  • 15
  • 26
  • I tried it too, but my attributes are private, and get_object_vars returns null – David Aug 25 '17 at 14:55
  • @David see my updated answer, can you add a method in you Test class ? like toArray – yoeunes Aug 25 '17 at 15:08
  • You can also use reflection http://php.net/manual/en/book.reflection.php to access private variables but as some other folks have suggested, your entire approach is probably wrong. – Cerad Aug 25 '17 at 15:09
  • @Cerad what's wrong with my approch :/ ? this is just a suggestion it works for the example :/ – yoeunes Aug 25 '17 at 15:13
  • @yoeunes - My "entire approach is wrong" was directed at David. Sorry for the confusion. Your suggestion will work. – Cerad Aug 25 '17 at 15:18