正在修改重复数组中的PHP对象

时间:2012-11-22 13:34:19

标签: php arrays

我有一个多维数组,有些元素是对象。我想最终得到2个数组,一个已经通过我的esc()函数传递了所有字符串值和对象属性,另一个是未修改的原始数据。

给出以下代码:

$raw = $data;
echo $raw['obj']->description; // Prints '< >Test Desc'

array_walk_recursive($data, function (&$item, $key){
   if(is_string($item)) {
      $item = esc($item);
   } elseif(is_object($item)) {
      foreach ($item as $property => $value)  {
          if(is_string($value)) {
              $item->$property = esc($value);
          }
      }
   }
});

echo $data['obj']->description; // Prints '&lt; &gt;Test Desc' - Correct
echo $raw['obj']->description; // Prints '&lt; &gt;Test Desc' - Incorrect

我希望$ raw完全不被修改,并且$ data已经通过esc()处理。除了对象属性之外,就是这种情况。由于某种原因,$ raw中的对象也被修改,因此两条echo行打印出不同的值,为什么会这样?

3 个答案:

答案 0 :(得分:3)

因为PHP 5对象总是按引用传递。

你必须“克隆”对象以真正复制它们。

有关详细信息,请参阅http://php.net/manual/en/language.oop5.references.php

答案 1 :(得分:1)

在PHP中通过引用传递对象。这意味着,如果您将对象$a分配给变量$b,则$a$b都将指向同一个对象。这在Objects and references手册页中有更详细的解释。

您可以使用clone运算符来真正克隆对象:

$b = clone $a;

这仅适用于对象,因此您必须以递归方式复制数组,并将clone用于对象。

答案 2 :(得分:1)

PHP的引擎盖下的pass-object-by-reference在这里工作。

简而言之,PHP自然地通过引用传递对象,这包括数组成员。如果您需要此证明,请尝试以下脚本:

<?php $arr = array(new stdClass()); var_dump($arr[0]); $arr2 = $arr; var_dump($arr[0]); ?>

两种情况下的输出都是object(stdClass)[1]

您可以使用几种解决方案。例如,您可以使用clone运算符作为对象。如果你知道数组的结构,这是微不足道的。如果你不这样做,你就会遇到问题,因为PHP不能clone数组(因此,你需要以递归方式遍历它)。所有其他解决方案都包括在编辑之前复制对象数据。