在内容类网站开发中,多级评论回复是提升用户互动体验的重要功能,CodeIgniter作为轻量级的PHP开发框架,能够很方便地实现无限级评论数据的递归处理。实现这个功能需要从数据库设计、后端逻辑处理到前端渲染三个环节配合完成。

数据库表结构设计
多级评论的核心是每条评论需要记录自身的父级评论ID,因此评论表需要包含以下核心字段:
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | int | 评论主键ID |
| content | text | 评论内容 |
| parent_id | int | 父级评论ID,顶级评论为0 |
| article_id | int | 所属文章ID |
| user_id | int | 评论用户ID |
| create_time | datetime | 评论创建时间 |
模型层递归查询实现
在CodeIgniter的模型中,我们需要先查询出所有评论,再通过递归函数将平级数据整理成层级结构。首先在application/models/目录下创建Comment_model.php:
<?php
class Comment_model extends CI_Model {
public function __construct() {
parent::__construct();
$this->load->database();
}
// 获取指定文章的所有评论
public function get_comments_by_article($article_id) {
$this->db->where('article_id', $article_id);
$this->db->order_by('create_time', 'ASC');
$query = $this->db->get('comments');
$comments = $query->result_array();
// 调用递归函数整理层级
return $this->build_comment_tree($comments);
}
// 递归构建评论树
private function build_comment_tree($comments, $parent_id = 0) {
$tree = array();
foreach ($comments as $comment) {
if ($comment['parent_id'] == $parent_id) {
// 查找当前评论的子评论
$children = $this->build_comment_tree($comments, $comment['id']);
if ($children) {
$comment['children'] = $children;
}
$tree[] = $comment;
}
}
return $tree;
}
}
控制器层数据传递
在控制器中调用模型获取整理好的层级评论数据,传递给视图层渲染。以Article控制器为例:
<?php
class Article extends CI_Controller {
public function detail($article_id) {
$this->load->model('Comment_model');
// 获取层级结构的评论数据
$data['comments'] = $this->Comment_model->get_comments_by_article($article_id);
$data['article_id'] = $article_id;
$this->load->view('article/detail', $data);
}
}
视图层嵌套渲染
视图层需要通过递归方式渲染不同层级的评论,我们可以在application/views/article/目录下创建detail.php视图文件,同时单独写一个递归渲染评论的局部视图:
首先创建comment_item.php局部视图,用于渲染单条评论及其子评论:
<?php
// 递归渲染评论的函数
function render_comment($comment, $level = 0) {
$margin_left = $level * 30;
?>
<div class="comment-item" style="margin-left: <?php echo $margin_left; ?>px; border-left: 2px solid #eee; padding-left: 10px; margin-bottom: 15px;">
<div class="comment-meta">
<span>用户ID:<?php echo $comment['user_id']; ?></span>
<span>发布时间:<?php echo $comment['create_time']; ?></span>
</div>
<div class="comment-content">
<?php echo htmlspecialchars($comment['content']); ?>
</div>
<!-- 回复按钮,点击后可以触发回复表单 -->
<button class="reply-btn" data-comment-id="<?php echo $comment['id']; ?>">回复</button>
<?php
// 如果存在子评论,递归渲染
if (isset($comment['children']) && !empty($comment['children'])) {
foreach ($comment['children'] as $child) {
render_comment($child, $level + 1);
}
}
?>
</div>
<?php
}
?>
然后在detail.php主视图中引入局部视图,渲染所有评论:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>文章详情</title>
</head>
<body>
<h1>文章详情页</h1>
<div class="comment-section">
<h2>评论区</h2>
<?php
// 加载局部视图中的渲染函数
$this->load->view('comment_item');
// 渲染所有顶级评论
if (!empty($comments)) {
foreach ($comments as $comment) {
render_comment($comment);
}
} else {
echo '<p>暂无评论,快来发表第一条评论吧</p>';
}
?>
</div>
<div class="comment-form">
<h3>发表评论</h3>
<form action="/article/add_comment" method="post">
<input type="hidden" name="article_id" value="<?php echo $article_id; ?>">
<input type="hidden" name="parent_id" id="parent_id" value="0">
<textarea name="content" rows="4" placeholder="请输入评论内容"></textarea>
<button type="submit">提交评论</button>
</form>
</div>
<script>
// 点击回复按钮时,设置父级评论ID
document.querySelectorAll('.reply-btn').forEach(btn => {
btn.addEventListener('click', function() {
const commentId = this.getAttribute('data-comment-id');
document.getElementById('parent_id').value = commentId;
document.querySelector('textarea[name="content"]').focus();
});
});
</script>
</body>
</html>
评论提交处理
最后需要在控制器中添加评论提交的接口,接收前端传递的评论内容、文章ID和父级评论ID,存入数据库:
<?php
class Article extends CI_Controller {
// 省略之前的detail方法
public function add_comment() {
$article_id = $this->input->post('article_id', true);
$parent_id = $this->input->post('parent_id', true);
$content = $this->input->post('content', true);
$user_id = $this->session->userdata('user_id'); // 假设用户登录后session中存了user_id
if (empty($content)) {
echo '<script>alert("评论内容不能为空");history.back();</script>';
return;
}
$data = array(
'article_id' => $article_id,
'parent_id' => $parent_id ? $parent_id : 0,
'content' => $content,
'user_id' => $user_id,
'create_time' => date('Y-m-d H:i:s')
);
$this->db->insert('comments', $data);
redirect('article/detail/' . $article_id);
}
}
注意事项
- 递归层级过深时可能会导致性能问题,建议可以限制最大评论层级,比如最多支持5级回复,超过后自动归为5级评论的子评论。
- 评论内容需要做安全过滤,使用
htmlspecialchars函数转义后再输出,避免XSS攻击。 - 如果评论数据量较大,可以先查询顶级评论,再通过父级ID异步加载子评论,减少初始请求的数据量。
CodeIgniter无限级递归多级评论评论回复修改时间:2026-07-20 10:06:39