1

我有一个多维数组,其中一些元素是对象。我想最终得到 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行打印了不同的值,这是为什么呢?

4

3 回答 3

3

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

您必须“克隆”对象才能真正复制它们。

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

于 2012-11-22T13:37:57.590 回答
1

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

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

$b = clone $a;

但是,这仅适用于对象,因此您必须递归地制作clone用于对象的数组的副本。

于 2012-11-22T13:39:57.083 回答
1

PHP 的底层传递对象-by-reference 在这里起作用。

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

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

输出将object(stdClass)[1]在这两种情况下。

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

于 2012-11-22T13:43:03.513 回答