Here is a simplefied code:
Class Bar
{
static $foo;
public function __construct(Foo $foo)
{
$this->foo = $foo;
$this->loop($foo,1);
}
public function loop(Foo $foo, $index)
{
$a = $foo->a;
if ($index < 3)
{
$a[$index]->var2 += $a[$index]->var1;
$a[$index]->var1 = 0;
$foo->dump();
$this->foo->dump();
$this->loop(new Foo($a),++$index);
}
}
}
$p = array(
new Baz(100,200),
new Baz(300,400),
new Baz(400,200),
new Baz(600,400)
);
new Bar(new Foo($p));
There are two problem with this code. maybe more;)
-
It looks like that the reallocation of var1 has an affect on $foo. I would expect that after i passed $foo->a to $a it doesnt have.
-
In the construct i assaigned $foo to $this->foo but after every loop it changes its value. Could some point me out where does $this->foo’s value change?
Some more Info
Definition of Foo Class
Class Foo
{
public $a;
public function __construct($a)
{
$this->a = $a;
}
public function dump($title="")
{
echo "<br/>================".$title."=============================";
echo "<table>";
for ($i=0; $i<sizeof($this->a); $i++)
{
echo "<tr>";
echo "<td>" . $this->a[$i]->var1 . "</td>";
echo "<td>" . $this->a[$i]->var2 . "</td>";
echo "</tr>";
}
echo "</table>";
}
}
The Baz Class
Class Baz
{
public $var1;
public $var2;
public function __construct($var1, $var2)
{
$this->var1=$var1;
$this->var2=$var2;
}
}
The results of dumps:
================IM foo dump=============================
100 200
0 700
400 200
600 400
================Im $this->foo dump=====================
100 200
0 700
400 200
600 400
================IM foo dump=============================
100 200
0 700
0 600
600 400
================Im $this->foo dump======================
100 200
0 700
0 600
600 400
The behaviour you are seeing is normal. When assigning objects to variables in PHP, you pass a reference, not the value; if you want to have copies instead of references, you have to create a clone.
For instance, in the following scenario:
$a, $b, $c are just “aliases” so to speak, that point to $blub; meaning setting any member of $a has a direct effect on $blub, and therefore $b and $c aswell.
By using the keyword clone however you can achieve the result you are looking for:
Here we have explicitly created independent copies, and thus modifying the contents of $a will not change $blub, $b, or $c.
Finally here’s how your example class could look like implementing clones to work on standalone objects:
Update
Simply cloning $foo was not enough due to the fact that an array of objects is passed around:
Even if you clone the object which hosts the array, the objects themselves within the array still point to the same objects, since the array is just holding references; when an object is cloned, array members and their contents are copied, including references. It takes a bit to get your head around the concepts of references and values but eventually you’ll see everything fits like a puzzle 🙂
Anyhow, in this specific case one has to clone the objects within the array before using them, and this is easily achieved with the following loop inside the Bar::loop function:
See the class above for the complete edit.