如何设置PHP网站内容审核:内容发布审核流程与权限配置方法
在内容驱动的网站中,内容审核是保障信息质量与合规性的关键环节。无论是企业官网、资讯平台还是用户生成内容(UGC)社区,设计一套完善的内容发布审核流程并合理配置权限,能有效避免不当信息传播、降低运营风险。本文将系统讲解如何在PHP环境中搭建内容审核体系,涵盖核心流程设计、数据库表结构、权限控制方法以及完整的代码实现。
一、内容审核的核心概念与流程设计
内容审核通常包含以下几个核心角色与状态:
- 内容提交者:普通用户或编辑,负责撰写和提交内容。
- 审核员:具有审核权限的管理人员,负责对提交的内容进行审核。
- 管理员:拥有最高权限,可配置审核规则、管理审核员。
- 内容状态:常见状态包括“待审核”、“审核通过”、“审核拒绝”、“草稿”等。
基本的审核流程如下:
- 用户或编辑提交内容,内容状态默认为“待审核”。
- 审核员在后台查看待审核列表,对内容进行审核。
- 审核通过的内容自动发布上线,审核拒绝的内容退回给提交者并附带理由。
- 审核员无法审核自己提交的内容(权限隔离)。
二、数据库表结构设计
合理的数据库设计是审核系统的基础。下面以文章内容审核为例,展示核心表结构。
2.1 用户表(users)
用户表存储所有用户信息,包含角色字段用于区分权限。
CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL,
`password` varchar(255) NOT NULL,
`email` varchar(100) DEFAULT NULL,
`role` enum('editor','reviewer','admin') NOT NULL DEFAULT 'editor',
`created_at` datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;2.2 内容表(contents)
内容表存储用户提交的文章,通过 status 字段记录审核状态,reviewer_id 记录审核人。
CREATE TABLE `contents` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(200) NOT NULL,
`body` text NOT NULL,
`author_id` int(11) NOT NULL,
`status` enum('draft','pending','approved','rejected') NOT NULL DEFAULT 'pending',
`reviewer_id` int(11) DEFAULT NULL,
`review_comment` text,
`created_at` datetime DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `author_id` (`author_id`),
KEY `status` (`status`),
KEY `reviewer_id` (`reviewer_id`),
CONSTRAINT `contents_ibfk_1` FOREIGN KEY (`author_id`) REFERENCES `users` (`id`),
CONSTRAINT `contents_ibfk_2` FOREIGN KEY (`reviewer_id`) REFERENCES `users` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;2.3 审核日志表(review_logs)
审核日志表用于记录每一次审核操作,方便追溯与审计。
CREATE TABLE `review_logs` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`content_id` int(11) NOT NULL,
`reviewer_id` int(11) NOT NULL,
`action` enum('approve','reject','recall') NOT NULL,
`comment` text,
`created_at` datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `content_id` (`content_id`),
KEY `reviewer_id` (`reviewer_id`),
CONSTRAINT `review_logs_ibfk_1` FOREIGN KEY (`content_id`) REFERENCES `contents` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;三、权限配置的实现
权限配置是审核系统的核心安全保障。这里采用基于角色的访问控制(RBAC)模式,通过 role 字段区分用户权限。
3.1 权限检查函数
在PHP中编写统一的权限检查函数,方便在控制器和视图中调用。
<?php
/**
* 检查用户是否有指定角色
* @param string $requiredRole 最低所需角色:editor, reviewer, admin
* @return bool
*/
function hasRole($requiredRole) {
session_start();
$roleHierarchy = [
'editor' => 1,
'reviewer' => 2,
'admin' => 3
];
$userRole = $_SESSION['user_role'] ?? 'editor';
$userLevel = $roleHierarchy[$userRole] ?? 1;
$requireLevel = $roleHierarchy[$requiredRole] ?? 1;
return $userLevel >= $requireLevel;
}
/**
* 权限检查中间件(用于控制器入口)
*/
function requireRole($requiredRole) {
if (!hasRole($requiredRole)) {
header('HTTP/1.1 403 Forbidden');
echo json_encode(['error' => '权限不足']);
exit;
}
}
?>3.2 权限配置示例:控制导航菜单可见性
在后台管理界面,根据用户角色动态显示或隐藏菜单项。
<?php
$menuItems = [
'dashboard' => ['label' => '控制台', 'role' => 'editor'],
'content_list' => ['label' => '我的内容', 'role' => 'editor'],
'pending_review' => ['label' => '待审核内容', 'role' => 'reviewer'],
'manage_users' => ['label' => '用户管理', 'role' => 'admin'],
];
foreach ($menuItems as $key => $item) {
if (hasRole($item['role'])) {
echo '<li><a href="/admin/' . $key . '">' . $item['label'] . '</a></li>';
}
}
?>四、内容发布审核流程的代码实现
下面实现完整的审核流程,包括内容提交、待审核列表、审核操作等核心功能。
4.1 内容提交接口
用户或编辑提交内容时,状态自动设为“待审核”。
<?php
// submit_content.php
require_once 'db.php'; // 数据库连接文件
require_once 'auth.php'; // 权限函数文件
session_start();
if (!isset($_SESSION['user_id'])) {
header('Location: /login.php');
exit;
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$title = trim($_POST['title']);
$body = trim($_POST['body']);
$authorId = (int)$_SESSION['user_id'];
// 基础验证
if (empty($title) || empty($body)) {
$error = '标题和内容不能为空';
} else {
$stmt = $pdo->prepare("INSERT INTO contents (title, body, author_id, status) VALUES (?, ?, ?, 'pending')");
$stmt->execute([$title, $body, $authorId]);
// 记录日志
$contentId = $pdo->lastInsertId();
$logStmt = $pdo->prepare("INSERT INTO review_logs (content_id, reviewer_id, action, comment) VALUES (?, ?, 'submit', '内容已提交,等待审核')");
$logStmt->execute([$contentId, $authorId]);
$success = '内容已提交,等待审核';
}
}
?>4.2 获取待审核内容列表(审核员专用)
审核员登录后,可以查看所有待审核的内容,但不能看到自己提交的内容。
<?php
// pending_list.php
require_once 'db.php';
require_once 'auth.php';
session_start();
requireRole('reviewer');
$currentUserId = (int)$_SESSION['user_id'];
// 查询待审核内容,排除自己提交的
$stmt = $pdo->prepare("
SELECT c.id, c.title, c.created_at, u.username AS author
FROM contents c
JOIN users u ON c.author_id = u.id
WHERE c.status = 'pending' AND c.author_id != ?
ORDER BY c.created_at ASC
");
$stmt->execute([$currentUserId]);
$pendingList = $stmt->fetchAll();
?>
<!DOCTYPE html>
<html>
<head>
<title>待审核内容</title>
</head>
<body>
<h1>待审核内容列表</h1>
<table border="1">
<tr>
<th>ID</th>
<th>标题</th>
<th>作者</th>
<th>提交时间</th>
<th>操作</th>
</tr>
<?php foreach ($pendingList as $item): ?>
<tr>
<td><?= $item['id'] ?></td>
<td><?= htmlspecialchars($item['title']) ?></td>
<td><?= htmlspecialchars($item['author']) ?></td>
<td><?= $item['created_at'] ?></td>
<td>
<a href="review.php?id=<?= $item['id'] ?>">审核</a>
</td>
</tr>
<?php endforeach; ?>
</table>
</body>
</html>五、管理员审核功能的实现
审核员在审核页面可以查看内容详情,并做出“通过”或“拒绝”的操作。
5.1 审核操作页面
<?php
// review.php
require_once 'db.php';
require_once 'auth.php';
session_start();
requireRole('reviewer');
$currentUserId = (int)$_SESSION['user_id'];
$contentId = (int)($_GET['id'] ?? 0);
if ($contentId <= 0) {
die('无效的内容ID');
}
// 获取内容详情,并验证不是自己提交的
$stmt = $pdo->prepare("
SELECT c.*, u.username AS author
FROM contents c
JOIN users u ON c.author_id = u.id
WHERE c.id = ? AND c.author_id != ?
");
$stmt->execute([$contentId, $currentUserId]);
$content = $stmt->fetch();
if (!$content) {
die('内容不存在或无权审核');
}
// 处理审核提交
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$action = $_POST['action'] ?? '';
$comment = trim($_POST['comment'] ?? '');
if ($action === 'approve') {
$newStatus = 'approved';
} elseif ($action === 'reject') {
$newStatus = 'rejected';
} else {
$error = '无效的操作';
}
if (isset($newStatus)) {
// 更新内容状态
$updateStmt = $pdo->prepare("UPDATE contents SET status = ?, reviewer_id = ?, review_comment = ? WHERE id = ?");
$updateStmt->execute([$newStatus, $currentUserId, $comment, $contentId]);
// 记录审核日志
$logStmt = $pdo->prepare("INSERT INTO review_logs (content_id, reviewer_id, action, comment) VALUES (?, ?, ?, ?)");
$logStmt->execute([$contentId, $currentUserId, $action, $comment]);
$success = '审核操作已完成';
// 重新加载内容信息
$content['status'] = $newStatus;
$content['review_comment'] = $comment;
}
}
?>
<!DOCTYPE html>
<html>
<head>
<title>内容审核</title>
</head>
<body>
<h1>内容审核</h1>
<?php if (isset($success)): ?>
<p style="color: green;"><?= $success ?></p>
<?php endif; ?>
<?php if (isset($error)): ?>
<p style="color: red;"><?= $error ?></p>
<?php endif; ?>
<h2>内容详情</h2>
<p><strong>标题:</strong><?= htmlspecialchars($content['title']) ?></p>
<p><strong>作者:</strong><?= htmlspecialchars($content['author']) ?></p>
<p><strong>内容:</strong></p>
<div style="border:1px solid #ccc; padding:10px;">
<?= nl2br(htmlspecialchars($content['body'])) ?>
</div>
<p><strong>当前状态:</strong>
<?php
$statusMap = [
'pending' => '待审核',
'approved' => '已通过',
'rejected' => '已拒绝',
'draft' => '草稿'
];
echo $statusMap[$content['status']] ?? '未知';
?>
</p>
<?php if ($content['status'] === 'pending'): ?>
<form method="post">
<label>审核意见:<br>
<textarea name="comment" rows="3" cols="50"></textarea>
</label>
<br>
<button type="submit" name="action" value="approve">审核通过</button>
<button type="submit" name="action" value="reject">审核拒绝</button>
</form>
<?php elseif ($content['status'] === 'rejected'): ?>
<p><strong>拒绝理由:</strong><?= htmlspecialchars($content['review_comment']) ?></p>
<?php endif; ?>
<p><a href="pending_list.php">返回待审核列表</a></p>
</body>
</html>5.2 用户查看自己提交的内容状态
普通用户或编辑可以查看自己提交的内容及其审核状态。
<?php
// my_contents.php
require_once 'db.php';
require_once 'auth.php';
session_start();
requireRole('editor');
$userId = (int)$_SESSION['user_id'];
$stmt = $pdo->prepare("
SELECT id, title, status, review_comment, created_at
FROM contents
WHERE author_id = ?
ORDER BY created_at DESC
");
$stmt->execute([$userId]);
$myContents = $stmt->fetchAll();
?>
<h1>我的内容</h1>
<table border="1">
<tr>
<th>标题</th>
<th>状态</th>
<th>审核意见</th>
<th>提交时间</th>
</tr>
<?php foreach ($myContents as $item): ?>
<tr>
<td><?= htmlspecialchars($item['title']) ?></td>
<td>
<?php
$statusMap = [
'draft' => '草稿',
'pending' => '待审核',
'approved' => '已通过',
'rejected' => '已拒绝'
];
echo $statusMap[$item['status']] ?? '未知';
?>
</td>
<td><?= htmlspecialchars($item['review_comment'] ?? '') ?></td>
<td><?= $item['created_at'] ?></td>
</tr>
<?php endforeach; ?>
</table>六、扩展与优化建议
6.1 多层级审核
对于重要内容,可以设计多级审核流程,例如“编辑提交 - 初级审核 - 高级审核 - 发布”。只需在内容表中增加 review_level 字段,并配合状态机即可实现。
6.2 审核通知机制
当内容状态发生变化时,通过邮件或站内信通知相关用户。可以在审核操作完成后,调用通知函数。
<?php
// 通知函数示例
function notifyUser($userId, $subject, $message) {
// 实现邮件发送或站内信记录
// 例如:mail($userEmail, $subject, $message);
}
?>6.3 内容撤回功能
允许用户在内容审核通过前撤回提交。只需要将状态改回“草稿”即可。
<?php
// recall_content.php
require_once 'db.php';
require_once 'auth.php';
session_start();
$userId = (int)$_SESSION['user_id'];
$contentId = (int)($_POST['id'] ?? 0);
$stmt = $pdo->prepare("UPDATE contents SET status = 'draft' WHERE id = ? AND author_id = ? AND status = 'pending'");
$stmt->execute([$contentId, $userId]);
if ($stmt->rowCount() > 0) {
// 记录日志
$logStmt = $pdo->prepare("INSERT INTO review_logs (content_id, reviewer_id, action, comment) VALUES (?, ?, 'recall', '内容已撤回')");
$logStmt->execute([$contentId, $userId]);
echo '内容已撤回';
} else {
echo '撤回失败,请检查内容状态';
}
?>七、总结
本文从数据库设计、权限配置、审核流程代码实现三个维度,系统讲解了如何在PHP网站中搭建内容审核系统。核心要点包括:
- 使用
status字段管理内容状态,结合reviewer_id记录审核人。 - 基于角色的访问控制(RBAC)确保审核员无法审核自己提交的内容。
- 通过审核日志表实现完整审计追溯。
- 提供用户端与审核端分离的界面,保证操作清晰高效。
这套方案可直接应用于中小型PHP项目,也可根据具体业务需求进行扩展,例如增加多级审核、自动化敏感词过滤、积分奖励机制等,从而构建更加完善的内容管理体系。