PHP项目如何实现评论审核功能?

wen PHP项目 3

PHP项目如何实现评论审核功能?从零搭建安全高效的评论系统

目录导读

  1. 为什么需要评论审核?
  2. 评论审核的核心功能设计
  3. 数据库表结构设计(MySQL+Redis)
  4. PHP后端实现:提交→审核→展示流程
  5. 敏感词过滤与自动拦截机制
  6. 管理员审核后台实现
  7. 性能优化与防刷策略
  8. 常见问题解答(FAQ)

为什么需要评论审核?

在PHP项目(如博客、电商、论坛)中,评论功能是用户互动的重要环节,但未经审核的评论可能带来三大风险:

PHP项目如何实现评论审核功能?

  • 垃圾广告:机器人刷屏推广链接
  • :政治敏感、色情、暴力词汇
  • 恶意攻击:SQL注入、XSS跨站脚本

审核模式对比

模式 优点 缺点
预审核(先审后发) 安全可控 延迟用户体验
后审核(先发后审) 用户反馈快 需快速响应
自动+人工混合 效率与安全平衡 技术实现复杂

推荐方案:采用自动过滤(敏感词/垃圾检测)+ 人工抽查的混合模式,既保证效率又降低风险。


评论审核的核心功能设计

一个完整的评论审核系统应包含:

1 用户端功能

  • 提交评论(含昵称、邮箱、内容)
  • 查看已通过审核的评论(分页展示)
  • 评论状态提示(“审核中”/“已拒绝”/“已通过”)

2 管理端功能

  • 待审核列表:按时间倒序排列
  • 审核操作:通过/拒绝/标记垃圾
  • 批量处理:全选操作
  • 敏感词管理:增删改敏感词库

3 自动处理机制

  • 敏感词匹配拦截(立即拒绝)
  • 超链接检测(标记为可疑)
  • 频率限制(同一IP/用户短时间重复提交)
  • 第三方API检测(如百度AI内容审核)

数据库表结构设计(MySQL+Redis)

1 评论主表(comments)

CREATE TABLE `comments` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `post_id` int(11) NOT NULL COMMENT '文章ID',
  `user_name` varchar(50) NOT NULL COMMENT '评论者昵称',
  `email` varchar(100) DEFAULT NULL COMMENT '邮箱',
  `content` text NOT NULL COMMENT '评论内容',
  `status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '状态:0待审,1通过,2拒绝',
  `ip_address` varchar(45) DEFAULT NULL COMMENT '用户IP',
  `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `updated_at` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `idx_post_id` (`post_id`),
  KEY `idx_status` (`status`),
  KEY `idx_created_at` (`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

2 敏感词表(sensitive_words)

CREATE TABLE `sensitive_words` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `word` varchar(100) NOT NULL,
  `created_at` datetime DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_word` (`word`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

3 Redis缓存设计

  • 评论计数comment:count:{post_id} 存储当前通过评论数
  • 防重复提交comment:submit:{ip}:{post_id} 设置60秒过期
  • 最新评论comment:latest:{post_id} 使用有序集合(ZSET)

PHP后端实现:提交→审核→展示流程

1 评论提交接口(需防XSS+SQL注入)

// submit_comment.php
public function submitComment($postId, $userName, $content) {
    // 1. 输入净化
    $userName = htmlspecialchars(strip_tags($userName), ENT_QUOTES, 'UTF-8');
    $content = htmlspecialchars(strip_tags($content), ENT_QUOTES, 'UTF-8');
    // 2. 防重复提交(Redis锁)
    $ip = $_SERVER['REMOTE_ADDR'];
    $lockKey = "comment:submit:{$ip}:{$postId}";
    if ($redis->exists($lockKey)) {
        return ['error' => '请勿频繁提交'];
    }
    $redis->setex($lockKey, 60, time());
    // 3. 自动审核检测
    $autoResult = $this->autoAudit($content);
    $status = $autoResult['status']; // 0待审/1通过/2拒绝
    // 4. 写入数据库
    $sql = "INSERT INTO comments (post_id, user_name, content, status, ip_address) VALUES (?, ?, ?, ?, ?)";
    $stmt = $db->prepare($sql);
    $stmt->execute([$postId, $userName, $content, $status, $ip]);
    return ['success' => true, 'comment_id' => $db->lastInsertId()];
}

2 评论列表展示(仅展示status=1)

public function getApprovedComments($postId, $page = 1, $perPage = 20) {
    $offset = ($page - 1) * $perPage;
    $sql = "SELECT id, user_name, content, created_at 
            FROM comments 
            WHERE post_id = ? AND status = 1 
            ORDER BY created_at DESC 
            LIMIT ? OFFSET ?";
    $stmt = $db->prepare($sql);
    $stmt->execute([$postId, $perPage, $offset]);
    return $stmt->fetchAll(PDO::FETCH_ASSOC);
}

敏感词过滤与自动拦截机制

1 Trie树敏感词检测(高性能方案)

class SensitiveFilter {
    private $trie = [];
    public function loadWords($words) {
        foreach ($words as $word) {
            $node = &$this->trie;
            for ($i = 0; $i < mb_strlen($word); $i++) {
                $char = mb_substr($word, $i, 1);
                if (!isset($node[$char])) {
                    $node[$char] = [];
                }
                $node = &$node[$char];
            }
            $node['end'] = true; // 标记单词结束
        }
    }
    public function check($text) {
        $len = mb_strlen($text);
        for ($i = 0; $i < $len; $i++) {
            $node = $this->trie;
            for ($j = $i; $j < $len; $j++) {
                $char = mb_substr($text, $j, 1);
                if (!isset($node[$char])) break;
                $node = $node[$char];
                if (isset($node['end'])) {
                    return true; // 发现敏感词
                }
            }
        }
        return false;
    }
}

2 自动审核策略组合

private function autoAudit($content) {
    // 策略1:敏感词检测
    if ($this->sensitiveFilter->check($content)) {
        return ['status' => 2]; // 直接拒绝
    }
    // 策略2:链接检测(超过2个链接标记为可疑)
    preg_match_all('/https?:\/\/[^\s]+/', $content, $links);
    if (count($links[0]) > 2) {
        return ['status' => 0]; // 进入人工审核
    }
    // 策略3:重复提交检测(同一用户连续相同内容)
    // ... 使用Redis比较上次内容
    return ['status' => 1]; // 自动通过
}

管理员审核后台实现

1 待审核列表页面

// admin/comments.php
$sql = "SELECT c.*, p.title as post_title 
        FROM comments c 
        LEFT JOIN posts p ON c.post_id = p.id 
        WHERE c.status = 0 
        ORDER BY c.created_at DESC 
        LIMIT 50";

前端操作按钮

  • ✅ 通过:update comments set status=1 where id=?
  • ❌ 拒绝:update comments set status=2 where id=?
  • 🗑️ 删除:delete from comments where id=?

2 批量操作优化

// 使用事务批量更新
$ids = explode(',', $_POST['ids']);
$db->beginTransaction();
$stmt = $db->prepare("UPDATE comments SET status = ? WHERE id = ?");
foreach ($ids as $id) {
    $stmt->execute([$newStatus, intval($id)]);
}
$db->commit();

性能优化与防刷策略

1 数据库查询优化

  • post_id + status 建立联合索引
  • 使用 LIMIT 分页,避免 OFFSET 过大(改用游标分页)
  • 评论计数缓存:每次审核通过后更新Redis计数

2 防刷机制

// 1. 时间限制:同一IP 60秒内只能评论一次
if ($redis->exists("comment:limit:ip:{$ip}")) {
    die('操作频繁');
}
// 2. 内容长度限制
if (mb_strlen($content) < 2 || mb_strlen($content) > 2000) {
    die('内容长度不合法');
}
// 3. 验证码(可选)
// 使用极验或Google reCAPTCHA

3 异步审核队列(高并发场景)

// 使用Redis列表作为队列
$redis->lpush('comment:audit_queue', json_encode([
    'comment_id' => $id,
    'content' => $content
]));
// 单独脚本处理审核
while ($data = $redis->brpop('comment:audit_queue', 5)) {
    $this->autoAudit($data['content']);
    // 更新状态
}

常见问题解答(FAQ)

Q1:评论审核需要每次查询数据库吗?

A:建议缓存已通过评论数量(Redis),列表页只查已通过的,待审核数量用 SELECT COUNT(*) WHERE status=0,但避免高频查询。

Q2:如何处理图片/附件评论的审核?

A:存储路径到数据库,审核时人工或调用图片鉴黄API(如腾讯云内容安全),通过后才显示图片链接。

Q3:用户能否修改已提交的评论?

A:建议不允许修改,或仅允许修改未审核的评论,修改后状态重置为待审核。

Q4:敏感词库如何更新?

A:建立后台管理页面,支持导入词典(txt文件,每行一个词),定期更新。

Q5:审核系统与现有评论插件(如Disqus)如何集成?

A:推荐自建,如果使用第三方,可以设置其内容同步到本地数据库后进行二次审核。


总结与最佳实践

实现PHP评论审核功能的关键点:

  1. 安全第一:防止XSS/SQL注入,使用预处理语句
  2. 分层审核:自动过滤(>80%)+ 人工审核(<20%)
  3. 缓存加速:Redis缓存评论数和最新评论
  4. 用户体验:提交后立即显示“审核中”,通过后异步刷新
  5. 日志记录:记录所有审核操作,方便回溯

通过以上实现,你可以构建一个既安全又高效的评论审核系统,既保护网站内容安全,又提升用户互动体验。

抱歉,评论功能暂时关闭!