Hi a good day to everyone. I am new to PHP and here I am trying to push multiple objects ($viewership_prj) to a single array ($viewership_prj_arr).
The first time I wrote the following. The resulting array was not correct.
Basically whenever a new object is pushed into the array, all existing objects in that array are overwritten with the properties of that newly pushed object.
$viewership_prj_arr = array();
$viewership_prj = (object) array();
foreach($projects as $prj)
{
/*...*/
$viewership_prj->title = $prj['project_title'];
$viewership_prj_arr[] = $viewership_prj;
// $viewership_prj_arr[] is [title1] after first loop
// [title2, title2] after second loop
// [title3, title3, title3] after third loop
// ...
}
Then I changed to this and it worked. I declared a new object inside each loop.
$viewership_prj_arr = array();
foreach($projects as $prj)
{
/*...*/
$viewership_prj = (object) array();
$viewership_prj->title = $prj['project_title'];
$viewership_prj_arr[] = $viewership_prj;
// $viewership_prj_arr[] is [title1] after first loop
// [title1, title2] after second loop
// [title1, title2, title3] after third loop
// ...
}
I was very confused.
The only reason I could think of is that when the object is pushed into the array, it was passed by reference and not by value. I tried looking up the manual https://www.php.net/manual/en/language.oop5.references.php#:~:text=Objects%20and%20references%20%C2%B6,passed%20by%20references%20by%20default%22.&text=A%20PHP%20reference%20is%20an,the%20object%20itself%20as%20value. but it is not making much sense to me.
Could someone help me clarify this? Much thanks in advance.
Oversimplified, PHP stores an object as
"identifier to object" => actual object
Creating a new object $object_1 = (object)[]
stores
"identifier to object 1" => actual object 1
$object_1 = "identifier to object 1"
The value of $object_1
is a reference to object 1 and NOT the actual object itself. They are two seperate items, linked by the identifier.
So, when you do
$object_1->title = "a";
$array[1] = $object_1;
$array[2] = $object_1;
$array[3] = $object_1;
Under the hood, it looks like:
"identifier to object 1" => actual object 1->title = "a"
$array[
1 => "identifier to object 1", // (actual object 1->title = "a")
2 => "identifier to object 1", // (actual object 1->title = "a")
3 => "identifier to object 1", // (actual object 1->title = "a")
];
Changing $object_1->title = "b"
sets
"identifier to object 1" => actual object 1->title = "b"
but doesn't change the identifiers in $array
. They remain "identifier to object 1", so all the elements of the array are now:
$array[
[1] => "identifier to object 1", // (actual object 1->title = "b")
[2] => "identifier to object 1", // (actual object 1->title = "b")
[3] => "identifier to object 1", // (actual object 1->title = "b")
];
Also $object_2 = $object_1
will only copy the "identifier to object 1". Both variables point to the same object:
$object_1 = "identifier to object 1"
$object_2 = "identifier to object 1"
Any variable containing a reference to the actual object 1 can change the actual object 1.
$object_1->title = "c";
or
$object_2->title = "c";
or
$array[3]->title = "c";
do all exactly the same, as they all contain a reference to the same actual object 1. So changing one means changing all.
If you want all array elements to have their own object, you either have to create a new object for each and every one of them or - if you want to use the values of the previous object - use clone.
$array = [];
$names = [ "John", "Jack", "Jill" ];
$object = (object)[];
$object->name = "";
$object->coffee = "black with sugar";
foreach( $names as $name ){
$object->name = $val; //change the name of the actual object
$array[] = clone $object; //create a new object with the current values of $object
}
Will output
$array[
stdClass Object ( name=> John, coffee=> black with sugar ),
stdClass Object ( name=> Jack, coffee=> black with sugar ),
stdClass Object ( name=> Jill, coffee=> black with sugar )
]
//$object only contains the last change!
$object = stdClass Object ( name=> Jill, coffee=> black with sugar )