【问题标题】:PHP Recursion and How to Get Array Variable to Maintain Value in Recursive CallPHP递归以及如何获取数组变量以在递归调用中保持值
【发布时间】:2020-02-11 01:27:10
【问题描述】:

我有一个具有顶级 cmets 的评论系统,每个评论系统都可以有无限级别的回复 cmets。我正在尝试将所有评论 id 的列表按降序排列到一个数组中。

当我将结果回显时,PHP/SQL 代码运行良好。但是,我想以数组中的正确顺序结束 cmets 列表。似乎当数组变量通过递归例程传递时,它失败了。我理解这是 PHP 递归中的变量范围问题。

要得到我想要的东西,有什么办法?

我的代码:

//get all comments and descendants for post id
function get_comment_list($db,$post_id) {  
        $comment_array = array();
        $sql = "SELECT comment_id FROM comments WHERE parent = 0 AND _post_id=".$post_id." "."ORDER BY dateTime DESC";
        $result = $db->query($sql); 
        $q = $result->fetchAll(PDO::FETCH_COLUMN, 0);//one level array with '0' parameter   
        foreach($q as $parent){
            echo $parent;echo '<br>';//first level parent comment
            $comment_array[] = $parent;//store comment_id's
            get_descendants($db,$parent,$comment_array);    
        }    
    return $comment_array;
}
//get all descendants of parent level comments
function get_descendants($db,$parent,$comment_array){
    $sql = "SELECT comment_id FROM comments WHERE parent = $parent ORDER BY dateTime DESC";
    $result = $db->query($sql);
    $q = $result->fetchAll(PDO::FETCH_COLUMN, 0);//one level array with '0' parameter   
    foreach($q as $item){
        echo '&nbsp;&nbsp;'.$item;echo '<br>';
        $comment_array[]=$item;//store comment_id's
        get_descendants($db,$item,$comment_array);
    }
}
$post_id = 199;
$comment_list = array();
$comment_list = get_comment_list($db,$post_id);
print_r($comment_list);

当我回显结果时,我得到了我想要的:

295
  296
  302
  297
  298
  299
  300
294
244
  304
  293
  288
  286
  287
  285
  284
  282
  281
  279
  280
241
  292
  289
  283
240
  290
237
  291
  238
  239
236
230
  235
  231
  232

当我 print_r() 数组时,我只得到顶级 id。在递归调用期间没有添加后代。

295
294
244
241
240
237
236
230

或者,如果您可以建议一个递归的 MYSQL 查询来执行降序?

基本数据结构是:

comment_id    comment    parent   post_id

parent 将comment_id 称为其父级。 parent = 0 是顶级父级。

【问题讨论】:

  • 你只有一条comment_id=0的记录吗?
  • 不,可以有多个父母的父母 = 0。比如说有人发布了一个视频。直接对帖子的评论将位于 parent = 0。对 cme​​ts 的回复将具有 parent = comment_id... 启用嵌套或分层回复。

标签: php mysql sql recursion


【解决方案1】:

我找到了使用会话数组变量的解决方法。它通过递归函数持续存在。调整后的代码:

$_SESSION['list']=array();
//get all comments and descendants for post id.  First get parents at = 0, then recurse through children/descendants
function get_comment_list($db,$post_id) {  
        $comment_array = array();
        $sql = "SELECT comment_id FROM comments WHERE parent = 0 AND _post_id=".$post_id." "."ORDER BY dateTime DESC";
        $result = $db->query($sql); 
        $q = $result->fetchAll(PDO::FETCH_COLUMN, 0);//one level array with '0' parameter   
        foreach($q as $parent){
            //echo $parent;echo '<br>';//first level parent comment
            $_SESSION['list'][] = $parent;//store comment_id's
            get_descendants($db,$parent);    
        }    
    return $_SESSION['list'];
}
//get all descendants of parent level comments
function get_descendants($db,$parent){
    $sql = "SELECT comment_id FROM comments WHERE parent = $parent ORDER BY dateTime DESC";
    $result = $db->query($sql);
    $q = $result->fetchAll(PDO::FETCH_COLUMN, 0);//one level array with '0' parameter   
    foreach($q as $item){
        //echo '&nbsp;&nbsp;'.$item;echo '<br>';
        $_SESSION['list'][]=$item;//store comment_id's
        get_descendants($db,$item);
    }
}
$post_id = 199;
$comment_list = get_comment_list($db,$post_id);
print_r($comment_list);
unset($_SESSION['list']);

【讨论】:

    【解决方案2】:

    这里是一个单循环递归来获取帖子
    和另一个递归循环显示在列表结果中
    保护递归(最多 40 级帖子)
    完整的可行代码 $database 在全局中使用以避免大堆栈 (我添加了一个(字符串)字段注释,您可以删除或替换它,它是出于测试目的)

    <html>
    
     <head>
         <style>
             ul {
                 border-left:solid 1px gray;
                 margin-top:1em;
             }
    
             ul span.bold {
                 font-weight:bold;
             }
         </style>
     </head>   
    
     <body>
    
    
    
    <H1>POSTs TEST</H1>
    
    <?php
    
    // get informations
    // @PARAM $startParent = first id parent, 
    // @PARAM $whereToAppend = $root = array to fill
    // @PARAM $level = increase each recursion, stop if greater than 40
    function getComments($startParent,&$whereToAppend,$level) {
    
      // use global database handler
      global $bdd;  
    
      // secure infinite loop !
      if ($level>40) { return; }
    
      // get alls post with id_parent=$startParent 
      $i=0;
      // NOTE you can append a SORT tag, DESC if you want etc...
      $sql="select comment_id, parent, comment from comments where parent=$startParent";
      $result = $bdd->query($sql);
      // prepare a structure to store one post
      while ($donnees = $result->fetch()) {
       $datas=array('comment_id'=>$donnees['comment_id'],
                     'parent'=>$donnees['parent'],
                     'comment'=>$donnees['comment']
                     );
    
       // for more readability  
       // this post has a id            
       $id=$datas['comment_id'];
    
       // store the post in three
       $whereToAppend[$i]['id']=$id;
       $whereToAppend[$i]['datas']=$datas;
       $whereToAppend[$i]['sub']=array();
    
       // next post (always for post who has a id_parent : see parameters)
       $i++;
      }
    
      // now recursion...
      foreach ($whereToAppend as $k=>$d) {
            // get posts who have parent_id=id of the post found  
            getComments($d['id'],$whereToAppend[$k]['sub'],$level+1);
      }
    
      return ;
    
    }
    
    
    // used to show result 
    // @param $start=array to iterate
    // @param $level=level , always 0 at first call
    function iterate($start,$level=0) {
        echo('<ul>');
        foreach ($start as $k=>$element) {
            echo("<li>");
            echo ("comment_id=<span class='bold'>{$element['datas']['comment_id']}</span><br>");
            echo ("id parent=<span class='bold'>{$element['datas']['parent']}</span><br>");
            echo ("comment=<span class='bold'>{$element['datas']['comment']}</span><br>");
            iterate($element['sub'],$level+1);
            echo("</li>");
        }
        echo('</ul>');
    }
    
    
    
    // MAIN
    $bdd = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'root', '');
    
    // prepare a array where to get informations
    $root=array();
    
    // get informations
    // first para 0=> id parent, try with another id parent to get partial tree
    // second param $root = array to fill
    // third param=0, level 0 = recursion start at 0
    getComments(0,$root,0);
    
    
    // show informations
    iterate($root,0);
    
    
    
    ?>
     </body>
    </html> 
    

    【讨论】:

      【解决方案3】:

      请试试这个>

          //get all comments and descendants for post id
          function get_comment_list($db,$post_id) {  
                  $comment_array = array();
                  $sql = "SELECT comment_id FROM comments WHERE parent = 0 AND _post_id=".$post_id." "."ORDER BY dateTime DESC";
                  $result = $db->query($sql); 
                  $q = $result->fetchAll(PDO::FETCH_COLUMN, 0);//one level array with '0' parameter   
                  foreach($q as $parent){
                      $comment_array[$parent] = get_descendants($db,$parent);
                      //Use Parent ID as a key then push all childs comment under this parent ID
                  }    
      
                  print_R($comment_array);die;
              return $comment_array;
          }
          //get all descendants of parent level comments
          function get_descendants($db,$parent,$childComment_array = array()){
             if(empty($childComment_array)){
                $repliedComments = array();
             }else{
                 $repliedComments = $childComment_array;
             }
      
              $sql = "SELECT comment_id FROM comments WHERE parent = $parent ORDER BY dateTime DESC";
              $result = $db->query($sql);
              $q = $result->fetchAll(PDO::FETCH_COLUMN, 0);//one level array with '0' parameter   
              foreach($q as $item){
                  $repliedComments[]=$item;
                  get_descendants($db,$item,$repliedComments);
              }
      
      return $repliedComments;
          }
      

      【讨论】:

      • 不太好用。向后和缺少后续级别并且不太正确。结果为:230:{0:“235”,1:“231”},236:{},237:{0:“291”,1:“238”},240:{0:“290” },241:{0:“292”,1:“289”,2:“283”},244:{0:“304”,1:“293”,2:“288”,3:“286” , 4: "285", 5: "284", 6: "282", 7: "281", 8: "279" }, 294: { }, 295: { 0: "296" }
      猜你喜欢
      • 2017-01-16
      • 2021-12-13
      • 1970-01-01
      • 1970-01-01
      • 2022-11-26
      • 2015-03-13
      • 1970-01-01
      • 2020-02-20
      • 2011-05-18
      相关资源
      最近更新 更多