Implementation code of php infinite comment nesting

  • 2021-09-20 19:35:00
  • OfStack

In the process of designing BB, I am also thinking about whether it is possible to realize the structure display and parent-child structure search of infinite classification without recursion, because if the algorithm here is not optimized, the consequences may be fatal! Imagine 1. If the number of comments in an article is 300, according to the normal recursive algorithm, the database must be queried at least 301 times, and there is no nesting. If there is one or two levels of nesting or the number of comments exceeds 1000, then the database is not directly down?
In fact, PHP's powerful array processing capability has helped us solve this problem quickly and conveniently. The following figure shows an infinite class of

Database structure:

IDparentID newsID commts
108 article ID is 8 comments
21 8 Response to ID 1 comment
328 Response to ID 2 comment

In order to present the comments of article number 8 nested in the foreground, we only need to query the database once, that is, "SELECT * FROM TABLE WHERE newsID = 8", and hand over the later recursive work to the powerful PHP array. The problem that may be involved here is the reorganization of the structural relationship of the array, that is, all the comments that stay in the first-level classification are put under their own parentID to form children items.
Below the BBComment class in this piece of code paste out, I hope to share my ideas with you, also hope that you can put forward a better and more efficient algorithm.

Method 1


/** 
 *  Press ID Condition is found recursively from the comment array  
 * 
 */ 
function getCommentsFromAryById($commtAry, $id) 
{ 
 if ( !is_array($commtAry) ) return FALSE; 
 foreach($commtAry as $key=>$value) { 
  if ( $value['id'] == $id ) return $value; 
  if ( isset($value['children']) && is_array($children) ) $this->getCommentsFormAryById($value['children'], $id); 
 } 
} 
/** 
 *  Append   Sub-comments   To   Main comment   In, and form children Subitem  
 * 
 * @param array $commtAry  Original comment data reference  
 * @param int $parentId  Main comment ID 
 * @param array $childrenAry  Values of sub-comments  
 */ 
function addChildenToCommentsAry($commtAry, $parentId, $childrenAry) 
{ 
 if ( !is_array($commtAry) ) return FALSE; 
 
 foreach($commtAry as $key=>$value) { 
  if ( $value['id'] == $parentId ) { 
   $commtAry[$key]['children'][] = $childrenAry; 
   return TRUE; 
  } 
  if ( isset($value['children']) ) $this->addChildenToCommentsAry($commtAry[$key]['children'], $parentId, $childrenAry); 
 } 
} 
 $result = $this->BBDM->select($table, $column, $condition, 0, 1000); 
 
 /*  Start reorganizing nested comment structure  */ 
 array_shift($result); 
 $count = count($result); 
 $i  = 0; 
 while( $i<$count ) { 
  if ( '0' != $result[$i]['parentId'] ) { 
   $this->addChildenToCommentsAry($result, $result[$i]['parentId'], $result[$i]); 
   unset($result[$i]); 
  } 
  $i++; 
 } 
 $result = array_values($result); 
 /*  Completion of reorganization  */ 

Implementation method 2

Core code from WordPress


<?php
$comments = array (
  array (
    'id' => '3',
    'parent' => '0'
  ),
  array (
    'id' => '9',
    'parent' => '0'
  ),
  array (
    'id' => '1',
    'parent' => '3'
  ),
  array (
    'id' => '2',
    'parent' => '3'
  ),
  array (
    'id' => '5',
    'parent' => '1'
  ),
  array (
    'id' => '7',
    'parent' => '1'
  )
);
function html5_comment($comment) {
  echo '<li>';
  echo 'id:', $comment['id'], ' parent:', $comment['parent'];
}
function start_el(& $output, $comment) {
  ob_start();
  html5_comment($comment);
  $output .= ob_get_clean();
}
function end_el(& $output) {
  $output .= "</li><!-- #comment-## -->\n";
}
function start_lvl(& $output) {
  $output .= '<ol class="children">' . "\n";
}
function end_lvl(& $output) {
  $output .= "</ol><!-- .children -->\n";
}
function display_element($e, & $children_elements, $max_depth, $depth, & $output) {
  $id = $e['id'];
  start_el($output, $e); // Start code for the current comment 
  if ($max_depth > $depth +1 && isset ($children_elements[$id])) { // If the maximum layer is not exceeded and an array of child elements exists 
    foreach ($children_elements[$id] as $child) {
      if (!isset ($newlevel)) { // No. 1 1 Secondary loop has no variable set $newlevel , so put $newlevel Set to true And start the start code for the child element ; No. 1 2 The second and subsequent loops have been set $newlevel, The start code of the child element will no longer be added. Because the same 1 Batch loop sibling element, so just need 1 The child element starts the code, and the loop content is juxtaposed. 
        $newlevel = true;
        start_lvl($output);
      }
      display_element_template($child, $children_elements, $max_depth, $depth +1, $output); //$child As a parameter, continue to look for subordinate elements 
    }
    unset ($children_elements[$id]); // After using the release variable, the value will not be judged repeatedly in the future , After recursion, continue to judge the remaining child elements 
  }
  if (isset ($newlevel) && $newlevel) { // If the child element is found earlier, the ending code of the child element will be executed here 
    end_lvl($output);
  }
  end_el($output); // End code of current comment 
}
function display_element_template($e, & $children_elements, $max_depth, $depth, & $output) {
  $id = $e['id'];
  display_element($e, $children_elements, $max_depth, $depth, $output);
  if ($max_depth <= $depth +1 && isset ($children_elements[$id])) { // If the maximum level is exceeded and child elements exist, use the $child Continue to search for parameters 
    foreach ($children_elements[$id] as $child) {
      display_element_template($child, $children_elements, $max_depth, $depth, $output);
    }
    unset ($children_elements[$id]); // Use up and release variables 
  }
}
function comments_list($comments) {
  $top_level_elements = array ();
  $children_elements = array ();
  foreach ($comments as $e) {
    if (0 == $e['parent']) {
      $top_level_elements[] = $e;
    } else {
      $children_elements[$e['parent']][] = $e;
    }
  }
  $output = '';
  foreach ($top_level_elements as $e) {
    display_element_template($e, $children_elements, 2, 0, $output);
  }
  //var_dump($children_elements);// Because every time it is used up, $children_elements Will release the variable after, so at the end $children_elements Is an empty array 
  return $output;
}
echo '<ol class="comment-list">', comments_list($comments), '</ol>';

Related articles: