php实现多级评论
实现多级评论的数据库设计
多级评论通常采用自关联表结构。创建一个comments表,包含以下字段:
CREATE TABLE comments (
id INT AUTO_INCREMENT PRIMARY KEY,
content TEXT NOT NULL,
user_id INT NOT NULL,
parent_id INT DEFAULT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (parent_id) REFERENCES comments(id) ON DELETE CASCADE
);
parent_id字段指向父级评论的ID,顶级评论的parent_id为NULL。
递归查询评论数据
使用递归CTE查询多级评论(MySQL 8.0+):
WITH RECURSIVE comment_tree AS (
SELECT id, content, user_id, parent_id, created_at, 0 AS depth
FROM comments
WHERE parent_id IS NULL
UNION ALL
SELECT c.id, c.content, c.user_id, c.parent_id, c.created_at, ct.depth + 1
FROM comments c
JOIN comment_tree ct ON c.parent_id = ct.id
)
SELECT * FROM comment_tree ORDER BY depth, created_at;
PHP处理递归数据
对于不支持递归CTE的MySQL版本,可以在PHP中处理递归:
function buildCommentTree($parentId = null, $depth = 0) {
$comments = [];
$stmt = $pdo->prepare("SELECT * FROM comments WHERE parent_id " .
($parentId === null ? "IS NULL" : "= ?"));
$params = $parentId === null ? [] : [$parentId];
$stmt->execute($params);
while ($comment = $stmt->fetch(PDO::FETCH_ASSOC)) {
$comment['replies'] = buildCommentTree($comment['id'], $depth + 1);
$comments[] = $comment;
}
return $comments;
}
前端展示嵌套评论
使用HTML和CSS展示多级评论结构:
<div class="comments">
<?php foreach ($commentTree as $comment): ?>
<div class="comment" style="margin-left: <?= $comment['depth'] * 30 ?>px">
<p><?= htmlspecialchars($comment['content']) ?></p>
<button class="reply-btn" data-comment-id="<?= $comment['id'] ?>">回复</button>
<?php if (!empty($comment['replies'])): ?>
<?php include 'comments_partial.php' ?>
<?php endif; ?>
</div>
<?php endforeach; ?>
</div>
AJAX添加新评论
使用jQuery处理评论提交:
$('.reply-btn').click(function() {
const parentId = $(this).data('comment-id');
$('#parent_id').val(parentId);
$('#comment-form').show();
});
$('#comment-form').submit(function(e) {
e.preventDefault();
$.post('/add_comment.php', $(this).serialize(), function(response) {
location.reload();
});
});
性能优化建议
对于大型评论系统,考虑以下优化措施:
- 添加
path字段存储评论路径(如"1/4/7"表示ID为7的评论的父路径) - 为
parent_id字段添加索引 - 实现分页加载评论
- 使用缓存减少数据库查询
完整示例代码
处理评论提交的PHP代码:
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$content = trim($_POST['content']);
$userId = (int)$_SESSION['user_id'];
$parentId = isset($_POST['parent_id']) ? (int)$_POST['parent_id'] : null;
$stmt = $pdo->prepare("INSERT INTO comments (content, user_id, parent_id) VALUES (?, ?, ?)");
$stmt->execute([$content, $userId, $parentId]);
header('Location: ' . $_SERVER['HTTP_REFERER']);
exit;
}






