我需要返回从一个人开始的'x'代数(作为$generations参数传递)的家庭数据(父母、兄弟姐妹和伴侣)(作为$id参数传递)。我不能假设有两个父母,这个特殊的家谱模型必须考虑到父母的动态数量(考虑到生物学和收养关系)。我认为我的递归是向后的,但我不知道怎么做。
下面的代码触发了我的基本子句5次,每一代一次,因为$generation不是针对每一组父级,而是针对每一个父级减少1。我想要的是,当获取初始人的所有父母的"x"代数时,基子句($generations==0)只触发一次。
public function fetchRelationships($id = 1, $generations = 5, $relationships = array())
{
$perId = $id;
if ($generations == 0) {
return $relationships;
} else {
$parents = $this->fetchParents($perId);
$relationships[$perId]['parents'] = $parents;
$relationships[$perId]['partners'] = $this->fetchPartners($perId);
if (!empty($parents)) {
--$generations;
foreach ($parents as $parentRel) {
$parent = $parentRel->getPer2();
$pid = $parent->getId();
$relationships[$perId]['siblings'][$pid] = $this->fetchSiblings($perId, $pid);
$perId = $pid;
$relationships[$perId] = $this->fetchRelationships($perId, $generations, $relationships);
}
}
return $relationships;
}
}
方法fetchPartners、fetchParents和fetchSiblings只获取匹配的实体。所以我不会把它们粘贴在这里。假设有2个父代,5代,每代有2个母代,那么返回数组应该包含62个元素,并且只有在填充了这62个元素后才应该触发基子句。
提前感谢您的帮助。
-----------编辑--------
删除fetchSiblings和fetchPartners代码进行重写,使其更易于阅读:
public function fetchRelationships($id = 1, $generations = 5, $relationships = array())
{
$perId = $id;
if ($generations == 0) {
return $relationships;
} else {
$parents = $this->fetchParents($perId);
$relationships[$perId]['parents'] = $parents;
if (!empty($parents)) {
--$generations;
foreach ($parents as $parentRel) {
$perId = $parentRel->getPer2()->getId();
$relationships[$perId] = $this->fetchRelationships($perId, $generations, $relationships);
}
}
return $relationships;
}
}
foreach ($parents as $parentRel)
循环中,为每个父级调用fetchRelationships
。这是两个分支,所以您将有两个对"基本子句"的调用。然后,对于他们的每个父母,你将有另外两个对"基本条款"的调用,依此类推…
此外,您正在来回传递relationships
,使其元素引用回自身。我意识到你只是在努力保留信息,但实际上你在创造很多不必要的自我参考。
试试这个
public function fetchRelationships($id = 1, $generations = 5)
{
$perId = $id;
$relationships = array();
if ($generations == 0) {
return $relationships;
} else {
$parents = $this->fetchParents($perId);
$relationships[$perId]['parents'] = $parents;
if (!empty($parents)) {
--$generations;
foreach ($parents as $parentRel) {
$perId = $parentRel->getPer2()->getId();
$relationships[$perId] = $this->fetchRelationships($perId, $generations);
}
}
return $relationships;
}
}
您仍然会多次命中基本子句,但这并不重要。
你可能会想"但我会丢失$relationships
中的一些数据",但你不会。所有这些都来自递归返回。
如果您要从数据库中提取它,您是否考虑过让查询为您完成所有的工作?
不确定你需要如何堆叠或排除数据,但这里有一种方法:
<?php
class TreeMember {
public $id;
// All three should return something like:
// array( $id1 => $obj1, $id2 => $obj2 )
// and would be based on $this->$id
public function fetchParents(){ return array(); }
public function fetchPartners(){ return array(); };
public function fetchSiblings(){ return array(); };
public function fetchRelationships($generations = 5)
{
// If no more to go
if ($generations == 0) { return; }
$branch = array();
$branch['parents'] = $this->fetchParents();
$branch['partners'] = $this->fetchPartners();
$branch['partners'] = $this->fetchSiblings();
// Logic
$generations--;
foreach($branch as $tmType, $tmArr)
{
foreach($tmArr as $tmId => $tmObj)
{
$branch[$tmType][$tmId] =
$mObj->fetchRelationships
(
$generations
)
);
});
return array($this->id => $branch);
}
}