Jump to content

[SOLVED] Threaded comment output with recursive function returns unwanted repeats


rash
 Share

Recommended Posts

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

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

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...