GeoffChapman
GeoffChapman

Reputation: 126

Cloning object based on content in PHP

I seem to be going round in circles here but i have a situation where I when reading some objects i may come across some that contain an array. When this happens i wish to produce new objects based upon the array for example

sourceObject(namespace\className)
    protected '_var1' => array('value1', 'value2')
    protected '_var2' => string 'variable 2'

Should become

childObject1(namespace\className)
    protected '_var1' => string 'value1'
    protected '_var2' => string 'variable2'

childObject2(namespace\className)
    protected '_var1' => string 'value2'
    protected '_var2' => string 'variable2'

However due to not quite getting my head around it my clones always end up with the same content (sometimes both are value1 sometimes value2)

Upvotes: 0

Views: 93

Answers (1)

hakre
hakre

Reputation: 197787

You could create a method like the following one:

trait classSplitClone
{
    public function splitClone($name)
    {

        if (!is_array($this->$name)) {
            return [$this];
        }

        $objs   = [];
        $values = $this->$name;
        $c      = 0;
        foreach ($values as $value) {
            $objs[]          = $c ? clone $this : $this;
            $objs[$c]->$name = $value;
            $c++;
        }

        return $objs;
    }
}

and then use it in your class(es) as a trait

class className
{
    use classSplitClone;

    protected $var1;
    protected $var2;

    function __construct($var1, $var2)
    {
        $this->var1 = $var1;
        $this->var2 = $var2;
    }
}

An example could look like:

$obj = new className(['value1', 'value2'], 'variable 2');

print_r($obj->splitClone('var1'));

Yielding the following results:

Array
(
    [0] => className Object
        (
            [var1:protected] => value1
            [var2:protected] => variable 2
        )

    [1] => className Object
        (
            [var1:protected] => value2
            [var2:protected] => variable 2
        )

)

Hope this helps. Alterantively you can access private and protected members also via ReflectionObject.


The full example code (Demo):

<?php
/**
 * @link http://stackoverflow.com/a/24110513/367456
 */

/**
 * Class classSplitClone
 */
trait classSplitClone
{
    public function splitClone($name)
    {

        if (!is_array($this->$name)) {
            return [$this];
        }

        $objs   = [];
        $values = $this->$name;
        $c      = 0;
        foreach ($values as $value) {
            $objs[]          = $c ? clone $this : $this;
            $objs[$c]->$name = $value;
            $c++;
        }

        return $objs;
    }
}

/**
 * Class className
 */
class className
{
    use classSplitClone;

    protected $var1;
    protected $var2;

    function __construct($var1, $var2)
    {
        $this->var1 = $var1;
        $this->var2 = $var2;
    }
}

/*
 * Example
 */
$obj = new className(['value1', 'value2'], 'variable 2');

print_r($obj->splitClone('var1'));

Upvotes: 1

Related Questions