我有一个多维数组,有些元素是对象。我想最终得到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 '< >Test Desc' - Correct
echo $raw['obj']->description; // Prints '< >Test Desc' - Incorrect
我希望$ raw完全不被修改,并且$ data已经通过esc()处理。除了对象属性之外,就是这种情况。由于某种原因,$ raw中的对象也被修改,因此两条echo
行打印出不同的值,为什么会这样?
答案 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
数组(因此,你需要以递归方式遍历它)。所有其他解决方案都包括在编辑之前复制对象数据。