Рекурсивная функция для комментариев и ответов PHP-приложения

У меня возникли трудности с концептуализацией рекурсивной функции для добавления ответов на комментарии, ответов на ответы, ответов на ответы на ответы и т. Д.

Это моя таблица комментариев:

введите описание изображения здесь

Который ДОЛЖЕН выглядеть что-то вроде этого при рендеринге:

введите описание изображения здесь

В его основе я могу отобразить каждый комментарий, связанный с article_id (за исключением тех, которые NOT NULL являются NOT NULL , конечно):

 $comments = $commentClass->fetch_article_comments($article_id); foreach($comments as $comment) { $comment_id = $comment['comment_id']; $member_id = $comment['member_id']; $comment_text = $comment['comment_text']; $comment_timestamp = timeAgo($comment['comment_timestamp']); //get time ago //render comment using above variables } 

Теперь я предполагаю, что мне нужно добавить рекурсивную функцию в конце вышеупомянутого оператора foreach , но мне еще нужно придумать что-нибудь отдаленно успешное, добавляя ответы комментариев и ответы на каждый ответ.

Может ли кто-нибудь помочь мне выполнить это или, возможно, указать мне в правильном направлении. Я не совсем знаком с рекурсивными функциями. Я проделал некоторое сканирование в Интернете и в stackoverflow, чтобы найти что-то, что помогает, но пока не нашел ничего полезного.

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

Благодарю.


редактировать


Используя приведенные ниже ответы, я только возвращаю результаты первого комментария, а затем он выполняет итерацию и отображает этот комментарий на неопределенный срок. Я не могу понять, почему?

Мой php:

 function display_comments($article_id, $parent_id=0, $level=0) { global $comment; global $member; global $signed_in; global $username; $comments = $comment->fetch_article_comments($article_id, $parent_id); foreach($comments as $data) { $comment_id = $data['comment_id']; $c_member_id = $data['member_id']; $comment_text = $data['comment_text']; $comment_timestamp = timeAgo($data['comment_timestamp']); //get time ago $member_data = $member->fetch_member_data($c_member_id); $c_member_username = $member_data['member_username']; $c_member_avatar = $member_data['member_avatar']; //render HTML here $parent = $data['comment_parent']; display_comments($article_id, $parent, $level+1); }//end foreach }//end display_comments() 

и мой запрос PDO:

 public function fetch_article_comments($article_id, $parent_id) { //$page = (int)(!isset($_GET['page'])) ? 0 : $_GET['page']; if ($parent_id > 0) { $parent_id = "= $parent_id"; } else { $parent_id = "IS NULL"; } $query = $this->db->prepare("SELECT * FROM `comments2` WHERE `article_id` = $article_id AND `comment_parent` $parent_id ORDER BY `comment_timestamp` DESC"); try{ $query->execute(); $comments = $query->fetchAll(); //returns an array $query->closeCursor(); return $comments; } catch(PDOException $e){ die($e->getMessage()); } } 

Ядро проблемы заключается в следующем:

 $comments = $commentClass->fetch_article_comments($article_id); 

Я предполагаю, что эта функция somwhere создает и запускает SQL, похожую на SELECT ... WHERE comments.article_id=$article_id . Этого недостаточно – вам нужно что-то вроде

 $comments = $commentClass->fetch_article_comments($article_id, $parent_id); 

это переводит в SQL, аналогичный SELECT ... WHERE comments.article_id=$article_id AND comments.comment_parent ($parent_id>0)?"=$parent_id":"IS NULL"

Теперь вы можете написать свою функцию PHP:

 function display_comments ($article_id, $parent_id=0, $level=0) { $comments = $commentClass->fetch_article_comments($article_id, $parent_id); foreach($comments as $comment) { $comment_id = $comment['comment_id']; $member_id = $comment['member_id']; $comment_text = $comment['comment_text']; $comment_timestamp = timeAgo($comment['comment_timestamp']); //get time ago //render comment using above variables //Use $level to render the intendation level //Recurse display_comments ($article_id, $comment_id, $level+1); } } 

И, наконец, назовите его с помощью display_comments ($article_id);

Вы могли бы сделать что-то вроде:

 function getCommentsForParent($parent="") { echo "<div class=\"comment\">"; $db = get("select your db logics where parent = $parent"); foreach ($db as $comment) { echo "print your comment in a box and make a div around the hole comments" getCommentsForParent($comment['parent_id']); } echo "</div>"; } 

вызывать функцию с getCommentsForParent()

С вашим кодом это должно быть что-то вроде:

 function getCommentForParent($parent="") { global $commentsClass, $article_id; $comments = $commentClass->fetch_article_comments($article_id,$parent); foreach($comments as $comment) { $comment_id = $comment['comment_id']; $member_id = $comment['member_id']; $comment_text = $comment['comment_text']; $comment_timestamp = timeAgo($comment['comment_timestamp']); //get time ago getCommentForParent($comment['parent']); } } 

Посмотрите внимательно, ive скорректировал ваши выборки article_comments. Теперь у него есть слушатель для $ parent. Убедитесь, что, когда ваш $ parent = "", класс будет выбирать только комментарии с пустым родителем.

invoke with getCommentsForParent()

Он автоматически перейдет через родителя. Конечно, это очень концептуально, но, учитывая ваш код, вы должны его повесить.