Home > database >  PHP: how to "clone from" another object of same class? 'Internally clone' curren
PHP: how to "clone from" another object of same class? 'Internally clone' curren

Time:05-10

In my current application I have a number of objects that are required repeatedly

To save overhead of instantiating the same object over and over again, I keep an array of 'known' objects.
I can check the input data against the array, and - if already set - use the existing object, else go ahead to instantiate the new object and add the pointer reference to the relevant known objects array.

In most use cases, I can check prior to instantiating the class:

if(array_key_exists($identifier,$known_ClassObjects)){
   $object = $known_ClassObjects[$identifier];
} else {
   $object = new Class($params);
}

However, in some cases I can only identify that the object I am instantiating already exists once already inside it.

In that case I would like to be able to do one of 2 things:

  1. return the OTHER (pre-existing) object instead of this one, e.g.
class Test{

    public function __construct($params){
        
        //apply processing to $params, resulting in $identifier 

        if(array_key_exists($identifier, $known_ClassObjects)){ //$known_ClassObjects is global

             return $known_ClassObjects[$identifier];

        } else {

             //continue __construct() logic

             return $this;
        }

    }
}

However, PHP ALWAYS returns the current object, even with code return $other_object;

  1. 'Internally Clone' the current object from the found one [of the same class, obv] so that when it returns, it has the correct relevant properties populated.

NOTE: including any parent/child class properties -> I want to make this object EXACTLY the same as the found one.

So, if there was a PHP function clone_from(), it would work something like:

if(array_key_exists($identifier,$known_ClassObjects)){
   $this->clone_from ($known_ClassObjects[$identifier]);

} else {
   //continue with __construct()

}
return $this;

Given that 1. doesn't work and 2. doesn't seem to exist, I have only been able to do this in very 'hacky' ways: iterating through all properties of source object and setting all properties of current object.

However, this has obvious issues esp. with extended parent/child classes etc. which then requires things like reflection classes.

This seems like there SHOULD be a really simple solution, but I have been unable to find one

CodePudding user response:

What you actually could do is using either a Singleton Pattern or a Factory pattern - in both cases, the creation of objects is controlled by some piece of code and you can decide, which object to return. Singleton already is a special form of a Factory pattern.

Consider this code

class Singleton {
    protected static $instance; 
    
    protected function __construct() { 
    }
    
    public static function instance() {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }
} 

The constructor is protected which will prevent a object construction from "outside" via new. However, there is also a static function instance with which somebody can request an object instance from the factory method.

$obj = Singleton::instance(); 

So, the (internal) object is created only once, and then delivered afterwards until the script ends.

CodePudding user response:

However, PHP ALWAYS returns the current object, even with code return $other_object;

Constructor is not a regular function. You do not return from it. If you are in __construct() you are already constructing the new object. Before proceed, I strongly recommend you read at least: https://www.php.net/manual/en/language.oop5.decon.php

You most likely need a helper method or factory that would deal with that instead. Putting the logic you tried to place into your constructor is wrong.

Also you missed to clarify what the $identifier really is. But if that's object's property, then you can expose it (i.e. via getter) and have it read for your comparison/whatever by other code.

  • Related