本文目录导读:

在 PHP 项目中实现内容审核功能,通常需要一个完整的流程,包括用户提交、审核人/系统审核、状态更新和前台展示。
以下是几种主流的实现方案和核心代码逻辑:
状态字段 + 人工审核
这是最常见、最可控的方式,在数据表中增加一个status字段,通过后台管理员手动审核。
数据库设计
在需要审核的表中(如 articles, comments, posts)添加字段:
ALTER TABLE articles ADD COLUMN `status` TINYINT NOT NULL DEFAULT 0 COMMENT '状态: 0=待审核, 1=审核通过, 2=审核不通过'; ALTER TABLE articles ADD COLUMN `reviewer_id` INT DEFAULT NULL COMMENT '审核人ID'; ALTER TABLE articles ADD COLUMN `review_time` DATETIME DEFAULT NULL COMMENT '审核时间'; ALTER TABLE articles ADD COLUMN `review_reason` VARCHAR(500) DEFAULT NULL COMMENT '审核不通过原因';
用户提交代码
时,Status 默认设置为 0(待审核)。
// user_submit.php <?php // 假设已经获取了表单数据 $title = $_POST['title']; $content = $_POST['content']; // 插入数据库,状态默认待审核 $sql = "INSERT INTO articles (title, content, user_id, status, created_at) VALUES (?, ?, ?, 0, NOW())"; $stmt = $pdo->prepare($sql); $stmt->execute([$title, $content, $userId]); echo "发布成功,请等待管理员审核。";
后台审核代码
管理员在后台进行审核操作,更新状态。
// admin_review.php
<?php
// 获取待审核的文章列表
$sql = "SELECT * FROM articles WHERE status = 0 ORDER BY created_at DESC";
$pendingArticles = $pdo->query($sql)->fetchAll();
// 处理审核操作
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$articleId = $_POST['article_id'];
$action = $_POST['action']; // 'approve' 或 'reject'
$reason = $_POST['reason'] ?? null;
$newStatus = ($action === 'approve') ? 1 : 2;
$sql = "UPDATE articles SET status = ?, reviewer_id = ?, review_time = NOW(), review_reason = ? WHERE id = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute([$newStatus, $adminId, $reason, $articleId]);
// 可以发送通知给用户(邮件、站内信等)
echo "审核完成。";
}
前台展示代码
前端只查询或显示状态为“审核通过”的内容。
// index.php <?php // 只获取审核通过的文章 $sql = "SELECT * FROM articles WHERE status = 1 ORDER BY created_at DESC LIMIT 20"; $articles = $pdo->query($sql)->fetchAll();
结合 AI 自动审核(敏感词 + 文本识别)
如果用户量很大,人工忙不过来,可以先让机器过滤一遍。
敏感词过滤
使用 DFA(确定性有限自动机)算法进行敏感词检测。
// SensitiveFilter.php
class SensitiveFilter {
private $dict = [];
public function loadWords(array $words) {
foreach ($words as $word) {
$this->addWord($word);
}
}
private function addWord($word) {
$len = mb_strlen($word);
$node = &$this->dict;
for ($i = 0; $i < $len; $i++) {
$char = mb_substr($word, $i, 1);
if (!isset($node[$char])) {
$node[$char] = [];
}
$node = &$node[$char];
}
$node['end'] = true; // 标记为敏感词结尾
}
public function hasSensitive($text) {
$len = mb_strlen($text);
for ($i = 0; $i < $len; $i++) {
$node = &$this->dict;
$j = $i;
while ($j < $len) {
$char = mb_substr($text, $j, 1);
if (isset($node[$char])) {
$node = &$node[$char];
if (isset($node['end'])) {
return true; // 发现敏感词
}
$j++;
} else {
break;
}
}
}
return false;
}
}
// 使用
$filter = new SensitiveFilter();
$filter->loadWords(['暴力', '色情']);
if ($filter->hasSensitive($content)) {
// 自动标记为待人工审核或退回
echo "内容包含敏感词,需要审核。";
$status = 2; // 或保持0
}
调用第三方内容安全 API
使用云服务(百度AI、阿里云、腾讯云等)的文本/图片审核接口。
// 使用阿里云内容安全(示例)
use AlibabaCloud\Client\AlibabaCloud;
function checkContent($text) {
AlibabaCloud::accessKeyClient('your-access-key', 'your-access-secret')
->regionId('cn-shanghai')
->asDefaultClient();
$result = AlibabaCloud::rpc()
->product('Green')
->version('2017-12-21')
->action('TextScan')
->method('POST')
->options([
'query' => [
'RegionId' => 'cn-shanghai',
'Content' => json_encode([
'tasks' => [['content' => $text]],
'scenes' => ['antispam']
]),
],
])
->request();
$body = $result->toArray();
// 解析结果:判断是否需要人工审核或拦截
// ...
}
自动化工作流(推荐)
结合方案一和方案二,形成一个自动化 + 人工兜底的流程:
- 用户提交 →
status = 0 - AI 预审:
- 通过:
status = 1(直接发布) - 疑似违规(中等风险):
status = 0(送入人工审核队列) - 明确违规(高风险):
status = 2(自动退回,需通知用户申诉)
- 通过:
- 人工复审(对 AI 没法判断的内容进行最终确认)。
队列 + 异步审核
为了避免用户提交时等待 AI 审核结果,可以使用消息队列(RabbitMQ, Redis,或 PHP 的 pcntl_fork)。
- 用户提交后,直接将数据写入数据库(
status = 0)。 - 将审核任务推送到队列(Redis List 或 RabbitMQ)。
- 后台消费者 Worker(一个常驻 PHP 脚本)从队列中取任务,调用 AI 接口或敏感词库审核。
- 审核完成后,Worker 更新数据库状态。
- (可选)通过 WebSocket 或轮询通知用户审核结果。
总结与建议
| 场景 | 推荐方案 | 说明 |
|---|---|---|
| 小型项目 / 用户少 | 方案一 | 纯人工审核,开发量小,可控。 |
| 中型项目 / 内容较多 | 方案一 + 敏感词预检 | 机器拦掉明显违规的,剩下人工审。 |
| 大型项目 / 海量 UGC | 方案一 + AI 自动审核 + 异步队列 | 高并发、高过滤率、人工只审长尾。 |
核心步骤总结:
- 加状态字段 (
status) - 写审核逻辑 (用户提交流程、后台审核流程、前台展示过滤)
- 加安全检测 (敏感词 + 云 API)
- 加通知机制 (审核通过/驳回后,通知用户)
特别注意: 如果你的项目有 App 端或需要实时反馈审核状态,建议使用 WebSocket 或 Server-Sent Events (SSE) 推送给用户,而不是让用户手动刷新页面。