我不太习惯递归函数,也不明白如何正确退出函数。
我尝试从数据库中的父项(使用 Laravel)识别子项(孙子等)列表。
public function getChildren($parentId, $allChildrenArray = Array()){
$children = DB::table('myTable')->where('parent',$parentId)->get();
if (sizeof($children)>0){
foreach ($children as $child) {
array_push($allChildrenArray,array($child->slug, $child->id));
MyController::getChildren($child->id, $allChildrenArray);
}
}else{
// var_dump($allChildrenArray); displays a proper array
return $allChildrenArray;
}
}
我对此有两个问题。
- 据我了解,我的脚本一旦遇到死胡同,它就会停止传播。但如果还有其他路径可供探索怎么办?
如果我显示
var_dump($allChildrenArray)
,则会显示一个数组,看起来没问题。 但是,如果我尝试从其他函数显示它,我会得到null
...public function doStuff($itemId){ $allChildrenArray = MyController::getChildren($itemId); var_dump($allChildrenArray); // displays null }
最佳答案
首先,您应该将助手放在 Controller 之外:)
更重要的是:要理解递归,它有助于逐步进行处理,当您到达递归时,假设我们正在做它应该做的事情,然后稍后再回到那里。
让我们这样开始:
/**
* Returns the children for a given parent
* @param int $parentId
* @return array
*/
public function getChildren($parentId){
$allChildrenArray = array();
$children = DB::table('myTable')->where('parent',$parentId)->get();
foreach ($children as $child) {
array_push($allChildrenArray, array($child->slug, $child->id));
// Here should be the recursion later
}
// var_dump($allChildrenArray); displays a proper array
return $allChildrenArray;
}
现在,如果您查看此函数,您会发现它适用于第一级。很容易看出,在遍历给定父级的子级时,如果您想添加递归,则需要获取这些后代。
/**
* Returns the children recursively for a given parent
* @param int $parentId
* @return array
*/
public function getChildren($parentId){
$allChildrenArray = array();
$children = DB::table('myTable')->where('parent',$parentId)->get();
foreach ($children as $child) {
array_push($allChildrenArray, array($child->slug, $child->id));
// get descendants of child
$furtherDescendants = $this->getChildren($child->id);
// add them to current list
foreach ($furtherDescendants as $desc) {
$allChildrenArray[] = $desc; // or use arraypush or merge or whatever
}
}
// var_dump($allChildrenArray); displays a proper array
return $allChildrenArray;
}
现在发生的情况是,当您到达第一个子级时,将开始新的 getChildren 函数运行,将该子级的 id 作为父级 id。如果它没有 child ,那么它将返回一个空数组,否则它将添加该 child 的信息,然后为孙子的 id 作为父 id 开始新的运行,并且...
如果传递数组,您可能可以节省一些内存,但在这种情况下,您需要将其作为引用。此外,当您首先调用此方法时,您需要传递一个变量作为将填充的输入。
/**
* Returns the children recursively for a given parent
* @param int $parentId
* @param &array $children
*/
public function getChildren($parentId, &$allChildrenArray) {
$children = DB::table('myTable')->where('parent',$parentId)->get();
foreach ($children as $child) {
array_push($allChildrenArray, array($child->slug, $child->id));
// get descendants of child
$this->getChildren($child->id, $allChildrenArray);
}
// var_dump($allChildrenArray); displays a proper array
return; // nothing to return, children info added to variable passed by reference
}
...
$kids=array();
$this->getChildren($parentId, $kids);
var_dump($kids)
只要确保不要混淆这两种不同的解决方案即可。
退出条件是给定父级没有子级时的情况。在这种情况下,foreach 将不会启动,因此不会进行进一步的递归调用。然而,这仅意味着退出该分支。
关于PHP 递归中断,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24480499/