PHP递归中断

时间:2014-06-29 21:35:48

标签: php recursion

我不习惯递归函数,我不明白如何正确退出函数。

我尝试从数据库中的父项(使用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;
    }
}

我对此有两个问题。

  1. 当我理解我的剧本时,它会在遇到死胡同时立即停止传播。但如果还有其他方法可以探索呢?
  2. 如果我显示var_dump($allChildrenArray),则显示一个似乎正常的数组。 但是,如果我尝试从其他函数显示它,我会得到null ...

    public function doStuff($itemId){
        $allChildrenArray = MyController::getChildren($itemId);
        var_dump($allChildrenArray); // displays null
    }
    

1 个答案:

答案 0 :(得分:2)

首先,您应该将助手放在控制器之外:)

更重要的是:要理解递归,它有助于逐步处理,当你进行递归时,假设我们假设它正在做它应该做的事情,然后再回到那里。

让我们这样开始:

    /**
     * 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开始。如果没有它的子项,那么它将返回一个空数组,否则它将为该子项添加信息,然后为孙子的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将不会启动,因此不会再进行进一步的递归调用。然而,这只意味着退出该分支。