I am having difficulty conceptualizing a recursive function for appending replies to comments, replies to replies, replies to replies to replies, etc.
This is my comments table:
Which SHOULD look something like this when rendered:
As it stands I can render each comment associated with the article_id (excluding those that are NOT NULL
, of course):
$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
}
Now I'm assuming I need to add a recursive function at the end of the above foreach
statement, but I have yet to come up with anything remotely successful in appending the comments replies and the replies to each reply.
Can anyone help me accomplish this or perhaps point me in the right direction. I am not entirely familiar with recursive functions. I have done some scanning of the internet and on stackoverflow looking for something that helps, but haven't found anything helpful yet.
I did come across this post which recommended using a hierarchical database system, but I think I would prefer to use a php recursive function for this.
Thanks.
edit
By using the below answers I am only returning the results first comment and then it iterates and displays that one comment indefinitely. I can't figure out why?
My 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()
and my PDO query:
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());
}
}
The core of the problem is this:
$comments = $commentClass->fetch_article_comments($article_id);
I assume, this function somwhere creates and runs SQL, that is similar to SELECT ... WHERE comments.article_id=$article_id
. This is not sufficient - you need something like
$comments = $commentClass->fetch_article_comments($article_id, $parent_id);
that translates into SQL similar to SELECT ... WHERE comments.article_id=$article_id AND comments.comment_parent ($parent_id>0)?"=$parent_id":"IS NULL"
Now you can write your PHP function:
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);
}
}
And finally call it with display_comments ($article_id);
You could do something like:
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>";
}
invoke function with getCommentsForParent()
With your code it should be something like:
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']);
}
}
Look closely, ive adjusted your fetch article_comments. It now has a listener for $parent. Make sure that when your $parent = "", the class will only select the comments with empty parent.
invoke with getCommentsForParent()
It will automatically loop through the parent. Ofcourse this is highly conceptual but given your code you should get the hang of it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With