PHP递归中断

PHP递归中断,php,recursion,Php,Recursion,我不太习惯递归函数,也不知道如何正确退出函数 我尝试从数据库中的父项(使用Laravel)中识别子项(孙子等)列表 关于这一点,我有两个问题 据我所知,一旦遇到死胡同,脚本就会停止传播。但是,如果还有其他途径需要探索呢 如果我显示一个var\u dump($allChildrenArray),则会显示一个看起来正常的数组。 但是,如果我试图从其他函数显示它,我会得到null public function doStuff($itemId){ $allChildrenArray = MyC

我不太习惯递归函数,也不知道如何正确退出函数

我尝试从数据库中的父项(使用Laravel)中识别子项(孙子等)列表

关于这一点,我有两个问题

  • 据我所知,一旦遇到死胡同,脚本就会停止传播。但是,如果还有其他途径需要探索呢
  • 如果我显示一个
    var\u dump($allChildrenArray)
    ,则会显示一个看起来正常的数组。 但是,如果我试图从其他函数显示它,我会得到
    null

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

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

    更重要的是:为了理解递归,一步一步地进行处理是有帮助的,当你开始递归时,假设它正在做它应该做的事情,然后再回到那里

    让我们这样开始:

        /**
         * 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不会启动,因此不会进行进一步的递归调用。但是,这只意味着退出该分支。

    理解它的最简单方法是在纸上手动完成所有步骤。“我得到
    null
    ”——因为如果
    sizeof($children)>0
    ,您将不会返回任何内容。您没有使用MyController::getChildren调用的结果。但是如果
    sizeof($children)>0
    ,如果有子对象,我会更新
    $allChildrenArray
    的值。然后我用一个更新后的子数组值和一个更新后的引用项重新启动同样的程序。我应该返回什么?“我更新$allChildrenArray的值”-并且什么也不做。你修改了一个变量,然后呢?它不是在你最初通过它的地方被神奇地修改的。非常感谢你给出了这个非常全面的答案!
        /**
         * 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)