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

I have a multidimensional array, and some of the elements are objects. I want to end up with 2 arrays, one which has had all string values and object properties passed through my esc() function, and one which is the unmodified original.

Given the following code:

$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

I would expect $raw to be entirely unmodified, and $data to have been processed through esc(). This is the case except for object properties. For some reason the object in $raw is also modified, so that the two echo lines print different values, why is this?

since PHP 5 objects are always pass-by-reference.

you have to "clone" the objects to really copy them.

see http://php.net/manual/en/language.oop5.references.php for details.

Objects are passed by reference in PHP. This means that if you assign an object $a to a variable $b, both $a and $b will point to the same object. This explained in more detail in the Objects and references manual page.

You can use the clone operator to really make a clone of an object:

$b = clone $a;

This only works for objects, though, so you must recursively make a copy of your array where you use clone for objects.

PHP's under-the-hood pass-object-by-reference is at work here.

In a nutshell, PHP naturally passes objects by reference, and this includes array members. If you want a proof of this, try the following script:

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

The output will be object(stdClass)[1] in both cases.

There are a couple of solutions for you to use. You can, for example, make use of the clone operator for objects. If you know the structure of the array, this is trivial. If you don't, you'll have an issue, as PHP cannot clone the array (and so, you'll need to recursively walk it). All the other solutions include duplicating your object data before editing it.