Rajesh Kumar
Rajesh Kumar

Reputation: 93

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)

Upvotes: 1

Views: 154

Answers (1)

SOFe
SOFe

Reputation: 8214

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.

Upvotes: 1

Related Questions