正在修改重复数组中的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 '< >Test Desc' - Correct
echo $raw['obj']->description; // Prints '< >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?
我有一个多维数组,有些元素是对象。 我想最终得到2个数组,一个已经通过我的esc()函数传递了所有字符串值和对象属性,另一个是未修改的原始数据。 p>
给出以下代码 : p>
$ raw = $ data;
echo $ raw ['obj'] - &gt; description; // Prints'&lt; &gt;测试描述'
array_walk_recursive($ data,function(&amp; $ item,$ key){
if(is_string($ item)){
$ item = esc($ item);
} elseif (is_object($ item)){
foreach($ item as $ property =&gt; $ value){
if(is_string($ value)){
$ item-&gt; $ property = esc($ value) ;
}
}
}
});
echo $ data ['obj'] - &gt; description; // Prints'&amp; lt; &amp; gt;测试描述' - 正确
echo $ raw ['obj'] - &gt;描述; // Prints'&amp; lt; &amp; gt;测试描述' - 不正确
code> pre>
我希望$ raw完全不被修改,并且$ data已经通过esc()处理。 除了对象属性之外,就是这种情况。 由于某种原因,$ raw中的对象也被修改,因此两个 echo code>行打印出不同的值,为什么会这样? p>
div>
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.