Rajesh Kumar Rajesh Kumar - 4 years ago 61
PHP Question

Function changing and returning object's value even if it is 'passed by value'

I am in a situation where i am mapping an array into object and then assigning it to another array. Simply making an array of object out of nested array.

array (size=2)
0 =>
array (size=3)
'edu_id' => string '3' (length=1)
'edu_degree' => string 'MCA' (length=3)
'edu_institute' => string 'ECB' (length=3)
1 =>
array (size=3)
'edu_id' => string '4' (length=1)
'edu_degree' => string 'BCA' (length=3)
'edu_institute' => string 'CET' (length=3)


This is the array and i am trying to convert it into this -

array (size=2)
0 =>
object(MatEducation)[11]
private 'id' => int 1
private 'eduId' => string '3' (length=1)
private 'degree' => string 'MCA' (length=3)
private 'institute' => string 'ECB' (length=3)
1 =>
object(MatEducation)[11]
private 'id' => int 1
private 'eduId' => string '4' (length=1)
private 'degree' => string 'BCA' (length=3)
private 'institute' => string 'CET' (length=3)


Here is the mapper function.

/**
* @param MatEducation $obj - i am passing this object so that
* function dont need to create 'new' object every time.if i create
* a new object then i get the desired result.
* @param array $arr this array contain the value to be converted.
* @return MatEducation
*/
public function toMatEducation(MatEducation $obj, array $arr)
{
$obj->setEduId($arr['edu_id']);
$obj->setDegree($arr['edu_degree']);
$obj->setInstitute($arr['edu_institute']);
return $obj;
}


And a call to mapper function is like -

/**return array of MatEducation Objects.*/
$arrayOfObject = array();
foreach ($result as $key=>$row) {
$arrayOfObject[$key] = $this->map->toMatEducation($education, $result[$key]);
}
return $arrayOfObject;


Since by default all the values are passed are 'pass by value' thus the
$education
object must not change and should return a copy of it from function. If its still changing than at the time of assignment to
$arrayOfObject[$key]
a new copy should be generated. So my question is why all the index of
$arrayOfObject
are pointing to same object.?
EDIT this is the array what i am getting now.

array (size=2)
0 =>
object(MatEducation)[11]
private 'id' => int 1
private 'eduId' => string '4' (length=1)
private 'degree' => string 'BCA' (length=3)
private 'institute' => string 'CET' (length=3)
1 =>
object(MatEducation)[11]
private 'id' => int 1
private 'eduId' => string '4' (length=1)
private 'degree' => string 'BCA' (length=3)
private 'institute' => string 'CET' (length=3)

Answer Source

Objects themselves are passed by value, but their properties aren't.

$a = new stdclass;
$a->p = 0;
$b = $a;
$b->p = 1;

$a->p would be changed into 0. If you change $b now, it would not affect $a itself, but changing the properties of $b would affect the properties of $a. Although they are not the same variable, they reference to the same object.

Note: That's not true to arrays though - two variables that are not by reference would not reference to the same array. For example, $a = [0]; $b = $a; $b[0] = 1; would not change the value of $a[0] unless it was $b =& $a, but this is not true for objects.

A simple solution to your case is to use clone. In your example, if you used toMatEducation(clone $education, ...) instead, it would work.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download