PHP-рекурсия и как получить переменную массива для поддержания значения в рекурсивном вызове - PullRequest
0 голосов
/ 14 октября 2019

У меня есть система комментариев, которая имеет комментарии верхнего уровня, и у каждого из них может быть бесконечный уровень комментариев. Я пытаюсь получить список всех идентификаторов комментариев в порядке убывания в массив.

Код PHP / SQL работает нормально, когда я просто выводю результаты. Однако я хотел бы закончить список комментариев в правильном порядке в массиве. Кажется, когда переменная массива передается через рекурсивные подпрограммы, происходит сбой. Я понимаю, что это проблема переменной области действия в рекурсии 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

Когда я печатаю массив, я получаю только идентификаторы верхнего уровня. Потомки не были добавлены во время рекурсивных вызовов.

295
294
244
241
240
237
236
230

Или, если вы можете предложить рекурсивный запрос MYSQL, который будет выполнять убывание в порядке?

Базовая структура данных:

comment_id    comment    parent   post_id

parent будет ссылаться на comment_id как на своего родителя. parent = 0 - родитель верхнего уровня.

Ответы [ 3 ]

0 голосов
/ 15 октября 2019

Я нашел способ использования переменной массива сеанса. Это сохраняется через рекурсивные функции. Скорректированный код:

$_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']);
0 голосов
/ 15 октября 2019

здесь рекурсия одного цикла для получения сообщений
и еще один цикл рекурсии для отображения в списке результатов
рекурсивная защита (макс. 40 уровней сообщений)
полная работоспособная база данных кода $, используемая в глобальном масштабе, чтобы избежать большихстек (я добавляю (строковое) поле комментария, вы можете удалить или заменить его, это было для целей тестирования)

<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> 
0 голосов
/ 14 октября 2019

Пожалуйста, попробуйте это>

    //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;
    }
...