rash Posted November 13, 2020 Share Posted November 13, 2020 Hi there, I’m struggling with a threaded comment system based on this function: <?php function renderComments($comments, $maxDepth = 0) { $out = ""; foreach($comments as $comment) : $out .= "\n<li>"; // add comment content here if($comment->children() && $maxDepth) { $out .= renderComments($comment->children, $maxDepth-1); } $out .= "</li>"; endforeach; if ($out) $out = "\n<ul class='level-".$maxDepth."'>".$out."</ul>\n"; return $out; } ?> Let’s say, there are 9 comments and 3 levels in this order: com-1 ---- com-2 --------- com-4 --------- com-5 --------- com-7 ---- com-3 --------- com-6 --------- com-8 --------- com-9 In this example, the function above returns: com-1 ---- com-2 --------- com-4 --------- com-5 --------- com-7 ---- com-3 --------- com-6 --------- com-8 --------- com-9 com-2 ---- com-4 ---- com-5 ---- com-7 com-3 ---- com-6 ---- com-8 ---- com-9 com-4 com-5 com-6 com-7 com-8 com-9 The problem is obviously caused by some logic issues in the recursion. When I use basically the same function for a page tree, everything works as expected. The comments seem to be structured different, especially their child roles. How can I stop the output after round 1 to get the expected result? Thanks in advance. Link to comment Share on other sites More sharing options...
rash Posted November 14, 2020 Author Share Posted November 14, 2020 Meanwhile I found a solution. It might be not the most elegant one, but leads straight to the expected result. Just in case someone else is interested: <?php /** * Render a nested list of comments to a page recursively * @param array $page->comments * @param int $maxDepth comment levels, usually the same as set in comments settings * @param array $doneComments, keeping ids of already processed comments * @return string * */ function renderComments($comments, $maxDepth = 0, $doneComments) { $out = ""; global $doneComments; foreach($comments as $comment) : $id = $comment->id; // comment already processed -> next loop if (in_array($id, $doneComments)) continue; // comment never seen before -> fill in array and go ahead $doneComments[] = $id; $out .= "\n<li>"; // add comment content here if($comment->children() && $maxDepth) { $out .= renderComments($comment->children, $maxDepth-1, $doneComments); } $out .= "</li>"; endforeach; if ($out) $out = "\n<ul class='level-".$maxDepth."'>".$out."</ul>\n"; return $out; } global $doneComments; $doneComments = array(); echo renderComments($page->comments, 3, $doneComments); ?> Each comment’s id goes into an array that labels it as 'done'. In the next loop we check the array whether the current comment is already 'done' and continue if so. Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now