In PHP, create an object of an expanding class from an instance of the base class

If I have a Foo class that extends the Bar class and an instance of Bar, is there any way to use this instance of Bar to “populate” a new instance of Foo?

In fact, I can only get Bar, but I want to use Foo in my code, as it gives me a lot of additional methods.

I saw quite a few solutions for similar issues, but they all seemed python or C #.

I cannot use ReflectionClass :: newInstanceArgs, since I cannot access the data that went into the Bar constructor to create it in the first place.

+4
source share
3 answers

There is no built-in way to easily do what you want. The interfaces of these classes need to be redesigned a bit. Perhaps something like:

<?php class Bar { ... } class Foo extends Bar { public static function fromBar(Bar $bar) { $foo = new self(); ... (copy data here) ... return $foo; } } 

+1
source

The recommended way to accomplish this is through dependency injection . Your constructor for Foo can take an instance of Bar , and then you have to write code to load the state of the new Foo object from the Bar object.

If PHP has a function that does exactly what you are describing, that would be problematic, because even if Foo extends Bar , the two classes can still be different. I don’t see how PHP can be smart enough to know how to automatically transfer an instance of one class to an instance of another class.

With that said, under the right circumstances, a (very hacky) “solution” below can do what you describe. I would not recommend using it. I basically just wanted to show that you have to resort to some strange things to do this.

 function convertObject($object, $newClass) { return unserialize( preg_replace( '/^O\:\d+\:"[^"]+"/', 'O:'.strlen($newClass).':"'.$newClass.'"', serialize($object) ) ); } 
+2
source

I just wrote that this example is based on the extension of user drivers, which may require an additional support package for the aforementioned main driver file.

 // File: parent.php class parent_class() { protected $_protected_object; // set in constructor protected $_protected_var = "Something dynamic"; public function __construct() { // keep in mind that if you don't override this constructor, this will execute when extended } public function create_resource() { $this->_protected_object = new SomeObjectInstance(); } public function child_class() { static $child = null; if (is_null($child)) { $file = "child.php"; if (!\file_exists($file)) { throw new Exception("Couldn't load '$file', doesn't exist"); } else { require_once($file); $child = new child_class(); $child->__overload("_protected_object", $this->_protected_object)->__overload("_protected_var", $this->_protected_var); } } return $child; } } // File: child.php class child_class extends parent_class { protected function __overload($index, &$value) { $this->$index =& $value; return $this; } public function __construct() { // REMEMBER: if you don't declare this method, the parent constructor will execute } public function extended_func() { // code } public function etc() { // code } } // Code instantiating objects: $parent = new parent_class(); $parent->create_resource(); var_dump($parent); /** * Would output something like this: * * object(parent_class)#1 (2) { * ["_protected_object":protected]=> * object(SomeObjectInstance)#2 (*) { * %OBJECT PROPERTIES% * } * ["_protected_var":protected]=> * string(17) "Something dynamic" * } */ $child = $parent->child_class(); var_dump($child); /** * Would output something like this: * * object(child_class)#3 (2) { * ["_protected_object":protected]=> * &object(SomeObjectInstance)#2 (*) { * %OBJECT PROPERTIES% * } * ["_protected_var":protected]=> * &string(17) "Something dynamic" * } */ 

Note that the second var_dump () for $ child displays the same information as $ parent, except that now you can see that the specified properties are preceded by ampersands (&), which means that now there are links. So, if you change anything in an instance of the parent class with respect to these two properties, it will be reflected in the instance of the child class.

0
source

Source: https://habr.com/ru/post/1413822/


All Articles