【问题标题】:Function changing and returning object's value even if it is 'passed by value'函数改变和返回对象的值,即使它是“按值传递”
【发布时间】:2015-12-25 15:17:57
【问题描述】:

我处于将数组映射到对象然后将其分配给另一个数组的情况。只需从嵌套数组中创建一个对象数组。

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)

这是数组,我正在尝试将它转换成这个 -

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)

这是映射器函数。

/**
     * @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;
    }

而对映射器函数的调用就像 -

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

由于默认情况下所有传递的值都是“按值传递”,因此$education 对象不能更改,并且应该从函数返回它的副本。如果它比分配给$arrayOfObject[$key] 时仍然变化,则应生成一个新副本。所以我的问题是为什么$arrayOfObject 的所有索引都指向同一个对象。? 编辑这是我现在得到的数组。

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)

【问题讨论】:

    标签: php


    【解决方案1】:

    对象本身是按值传递的,但它们的属性不是。

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

    $a->p 会变成 0。如果现在更改$b,不会影响$a 本身,但更改$b属性 会影响@ 的属性987654326@。虽然它们不是同一个变量,但它们引用的是同一个对象。

    注意:这不适用于数组——两个非引用变量不会引用同一个数组。例如,$a = [0]; $b = $a; $b[0] = 1; 不会更改 $a[0] 的值,除非它是 $b =& $a,但对于对象则不是这样。

    一个简单的解决方案是使用clone。在您的示例中,如果您改用 toMatEducation(clone $education, ...),它将起作用。

    【讨论】:

    • 谢谢你我现在明白了。还有一个额外的问题.. 像object(MatEducation)[11] this [11] 这样的每个对象的方括号中的内容是什么?
    • 我不太确定。我不知道您使用了哪种 var 打印方法,但我想这与对象的标识符有关。 php -r 'var_dump(new stdclass);' 输出object(stdClass)#1 (0),其中#1 表示它是此运行时中构造的第一个对象(我猜),可能与您的[11] 相同。
    • 我只是在做var_dump。是的,它们是对象的标识符,如果无论类如何创建新对象,它们都会从 1 开始计数,脚本递增 1。如果两个对象是克隆的,那么它们的标识符将是相同的。再次感谢你。和Marry Chrishmass
    • “克隆”是指$b = clone $a 还是$b = $a
    • 如果$a首先被创建,那么它的id为1。我克隆$b = clone $a然后$b的id为1。如果$b不是一个克隆而是独立的对象(相同或任何类)然后它将具有 id 2(或取决于在 $a$b 之间创建的对象数量).. 抱歉英语不好
    猜你喜欢
    • 2014-06-05
    • 1970-01-01
    • 2018-07-20
    • 1970-01-01
    • 2016-11-09
    • 2022-07-04
    • 1970-01-01
    • 1970-01-01
    • 2013-09-05
    相关资源
    最近更新 更多