PHP实现CMS评论嵌套数组结构:循环逻辑求助
Hey there! Let's tackle that nested comment structure problem you're working on for your CMS. I see you've got a flat array of comments and want to convert it into a nested structure with children arrays—let's fix this up properly.
First, let's clarify the input structure you provided:
$comments = [ ['comment_id' => 1, 'comment_repay_to' => null], ['comment_id' => 2, 'comment_repay_to' => 1], ['comment_id' => 3, 'comment_repay_to' => 2], ['comment_id' => 4, 'comment_repay_to' => null] ];
(Note: I'm assuming your comments are arrays; if they're objects, just replace array access like $comment['comment_id'] with object property access $comment->comment_id.)
Method 1: Recursive Approach (Clean & Intuitive)
This aligns with the recursive threaded comments solution you referenced. We'll use a helper function to recursively fetch child comments for each parent:
/** * Recursively get child comments for a given parent ID * @param int|null $parentId ID of the parent comment * @param array $comments Full list of flat comments * @return array Nested child comments */ function getChildComments($parentId, $comments) { $children = []; foreach ($comments as $comment) { if ($comment['comment_repay_to'] === $parentId) { // Add the comment with its own nested children $children[] = [ 'comment' => $comment, 'children' => getChildComments($comment['comment_id'], $comments) ]; } } return $children; } // Build the final nested structure $nestedComments = []; foreach ($comments as $comment) { // Top-level comments have no parent if ($comment['comment_repay_to'] === null) { $nestedComments[] = [ 'comment' => $comment, 'children' => getChildComments($comment['comment_id'], $comments) ]; } }
This works by:
- First identifying all top-level comments (where
comment_repay_toisnull) - For each top-level comment, recursively finding all comments that reply to it, and their replies, and so on
Method 2: Iterative Mapping (More Efficient for Large Datasets)
If you're dealing with a large number of comments, an iterative approach is better for performance. We'll first create a map of comment IDs to their nested structure, then link children to parents:
// Step 1: Create a map of comment IDs to nested comment structures $commentMap = []; $nestedComments = []; foreach ($comments as $comment) { $commentMap[$comment['comment_id']] = [ 'comment' => $comment, 'children' => [] ]; } // Step 2: Link each comment to its parent's children array foreach ($comments as $comment) { $parentId = $comment['comment_repay_to']; if ($parentId === null) { // Add top-level comments directly to the result $nestedComments[] = $commentMap[$comment['comment_id']]; } else { // Ensure the parent exists before adding the child if (isset($commentMap[$parentId])) { $commentMap[$parentId]['children'][] = $commentMap[$comment['comment_id']]; } } }
This method only loops through the comments twice, making it faster for large datasets compared to recursion.
Fixing Your Original Code
Your initial approach tried using a $level variable and while loop, but the logic for linking children to parents was missing. Nested comment levels can vary dynamically (a comment might have a reply that has another reply, etc.), which is hard to handle with a fixed level counter. The recursive or mapping methods above are much more straightforward for this use case.
When you run either solution, your $nestedComments will look like this:
[ [ 'comment' => ['comment_id' => 1, 'comment_repay_to' => null], 'children' => [ [ 'comment' => ['comment_id' => 2, 'comment_repay_to' => 1], 'children' => [ [ 'comment' => ['comment_id' => 3, 'comment_repay_to' => 2], 'children' => [] ] ] ] ] ], [ 'comment' => ['comment_id' => 4, 'comment_repay_to' => null], 'children' => [] ] ]
内容的提问来源于stack exchange,提问作者Hamza Dhamiya

