好的,我真的很喜欢这个。我希望你能帮助我。
我有我的班级,用于管理分层数据。输入是一个普通数组,具有以下结构(仅作为示例):
$list = array(
(object) array('id' => 1, 'nombre' => 'Cámaras de fotos', 'parentId' => null),
(object) array('id' => 2, 'nombre' => 'Lentes', 'parentId' => null),
(object) array('id' => 3, 'nombre' => 'Zoom', 'parentId' => 2),
(object) array('id' => 4, 'nombre' => 'SLR', 'parentId' => 1),
(object) array('id' => 5, 'nombre' => 'Primarios', 'parentId' => 2),
(object) array('id' => 6, 'nombre' => 'Sensor APS-C', 'parentId' => 4),
(object) array('id' => 7, 'nombre' => 'Full-frame', 'parentId' => 4),
(object) array('id' => 8, 'nombre' => 'Flashes', 'parentId' => null),
(object) array('id' => 9, 'nombre' => 'Compactas', 'parentId' => 1)
);
我以这种方式将数据输入到类中:
$Hierarchical = new Hierarchical;
$Hierarchical->plain = $list;
然后我有一个公共函数(createTree
)来创建列表的多维数组表示。它完美地运作。它可以返回结果或将其存储在$this->tree
中。
如您所见,这很简单。它调用私有函数iterateTree
,它是递归函数。
class Hierarchical {
public $plain = array();
public $tree = array();
public function createTree($parentId=0, $return=false) {
$tree = $this->iterateTree($parentId);
if(!$return) {
$this->tree = $tree;
} else {
return $tree;
}
}
private function iterateTree($parentId) {
$resArray = array();
foreach($this->plain as $item) {
if($item->parentId == $parentId) {
$children = $this->iterateTree($item->id);
if( count($children) > 0 ) {
$item->children = $children;
}
$resArray[] = $item;
}
}
return $resArray;
}
}
到目前为止一切顺利。它工作正常。
但是...... 当我想在调用$this->plain
后使用createTree()
时出现问题。它不是返回原始数据集,而是返回原始输入之间的某种混合,并附加所有子项(类似于$this->tree
)。
我无法弄清楚为什么$this->plain
的内容被更改,在所使用的两个函数中都没有改变它的内容。
我已尝试在foreach
之后取消foreach
内的变量,甚至将原始数组作为参数传递,而不是在递归函数中使用$this->plain
。没有任何效果。
我也不使用类中可能改变其值的任何其他函数。
这是一个完全的错误!
答案 0 :(得分:1)
在foreach
循环中$item
将是对数组中对象的引用,因此您要更改行中的同一对象
$item->children = $children;
这会影响原始数组$list
和$this->plain
中引用的对象。
一种解决方案可能是在你的foreach循环中克隆$item
。
答案 1 :(得分:1)
根据Doug的回答,正确的功能是:(添加$itemAux = clone $item
)
private function iterateTree($parentId) {
$resArray = array();
foreach($this->plain as $item) {
$itemAux = clone $item;
if($itemAux->parentId == $parentId) {
$children = $this->iterateTree($itemAux->id);
if( count($children) > 0 ) {
$itemAux->children = $children;
}
$resArray[] = $itemAux;
}
}
return $resArray;
}
答案 2 :(得分:0)
要添加Doug的答案,尽管手册中说“对象不通过引用传递”(http://www.php.net/manual/en/language.oop5.references。 php),它可能有助于将对象视为与可能“包含”它们的任何变量完全独立的实体,并且它们实际上是通过引用传递到任何地方...
class testClass
{
public $var1 = 1;
}
function testFunc($obj)
{
$obj->var1 = 2;
}
$t = new testClass;
testFunc($t);
echo $t->var1; // 2
因此,当您执行$item->children = $children;
时,实际上影响了$plain
数组中的每个原始对象。