本文目录导读:

我来详细介绍PHP实现留言反馈功能的完整方案,包含数据库设计、前端表单、后端处理和列表展示。
数据库设计
首先创建留言反馈表:
CREATE TABLE `feedback` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(50) NOT NULL COMMENT '留言人姓名', `email` varchar(100) DEFAULT NULL COMMENT '电子邮箱', `phone` varchar(20) DEFAULT NULL COMMENT '联系电话', varchar(200) NOT NULL COMMENT '留言标题', `content` text NOT NULL COMMENT '留言内容', `category` varchar(30) DEFAULT 'general' COMMENT '留言类型', `status` tinyint(1) DEFAULT 0 COMMENT '状态:0未处理,1已处理', `reply` text DEFAULT NULL COMMENT '管理员回复', `ip_address` varchar(45) DEFAULT NULL COMMENT 'IP地址', `created_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `updated_at` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`), KEY `status` (`status`), KEY `created_at` (`created_at`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='留言反馈表';
数据库连接类
config/database.php:
<?php
class Database {
private $host = 'localhost';
private $db_name = 'your_database';
private $username = 'root';
private $password = '';
private $conn;
public function getConnection() {
$this->conn = null;
try {
$this->conn = new PDO(
"mysql:host={$this->host};dbname={$this->db_name};charset=utf8mb4",
$this->username,
$this->password
);
$this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e) {
echo "连接失败: " . $e->getMessage();
}
return $this->conn;
}
}
?>
提交留言页面
feedback_form.php:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">留言反馈</title>
<style>
.feedback-form {
max-width: 600px;
margin: 50px auto;
padding: 20px;
border: 1px solid #ddd;
border-radius: 5px;
}
.form-group {
margin-bottom: 15px;
}
.form-group label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}
.form-group input,
.form-group select,
.form-group textarea {
width: 100%;
padding: 8px;
border: 1px solid #ddd;
border-radius: 3px;
}
.form-group textarea {
height: 150px;
resize: vertical;
}
.submit-btn {
background-color: #007bff;
color: white;
padding: 10px 20px;
border: none;
border-radius: 3px;
cursor: pointer;
}
.submit-btn:hover {
background-color: #0056b3;
}
.error-message {
color: red;
margin-bottom: 10px;
}
.success-message {
color: green;
margin-bottom: 10px;
}
</style>
</head>
<body>
<div class="feedback-form">
<h2>留言反馈</h2>
<?php if (isset($_GET['success'])): ?>
<div class="success-message">留言提交成功!</div>
<?php endif; ?>
<?php if (isset($_GET['error'])): ?>
<div class="error-message">
<?php echo htmlspecialchars($_GET['error']); ?>
</div>
<?php endif; ?>
<form action="process_feedback.php" method="POST">
<div class="form-group">
<label for="name">姓名 *</label>
<input type="text" id="name" name="name" required maxlength="50">
</div>
<div class="form-group">
<label for="email">电子邮箱</label>
<input type="email" id="email" name="email" maxlength="100">
</div>
<div class="form-group">
<label for="phone">联系电话</label>
<input type="tel" id="phone" name="phone" maxlength="20">
</div>
<div class="form-group">
<label for="category">留言类型</label>
<select id="category" name="category">
<option value="general">一般咨询</option>
<option value="suggestion">意见建议</option>
<option value="complaint">投诉反馈</option>
<option value="other">其他</option>
</select>
</div>
<div class="form-group">
<label for="title">留言标题 *</label>
<input type="text" id="title" name="title" required maxlength="200">
</div>
<div class="form-group">
<label for="content">留言内容 *</label>
<textarea id="content" name="content" required maxlength="2000"></textarea>
</div>
<button type="submit" class="submit-btn">提交留言</button>
</form>
</div>
</body>
</html>
处理留言提交
process_feedback.php:
<?php
session_start();
require_once 'config/database.php';
// 创建验证码校验(可选)
// if ($_POST['captcha'] !== $_SESSION['captcha']) {
// header('Location: feedback_form.php?error=验证码错误');
// exit;
// }
// 验证字段
$errors = [];
$name = trim($_POST['name'] ?? '');
$email = trim($_POST['email'] ?? '');
$phone = trim($_POST['phone'] ?? '');
$category = trim($_POST['category'] ?? 'general');
$title = trim($_POST['title'] ?? '');
$content = trim($_POST['content'] ?? '');
// 基本验证
if (empty($name)) {
$errors[] = '姓名不能为空';
}
if (empty($title)) {
$errors[] = '标题不能为空';
}
if (empty($content)) {
$errors[] = '留言内容不能为空';
}
if (!empty($email) && !filter_var($email, FILTER_VALIDATE_EMAIL)) {
$errors[] = '邮箱格式不正确';
}
// 长度验证
if (mb_strlen($name) > 50) {
$errors[] = '姓名不能超过50字';
}
if (mb_strlen($title) > 200) {
$errors[] = '标题不能超过200字';
}
if (mb_strlen($content) > 2000) {
$errors[] = '留言内容不能超过2000字';
}
if (!empty($errors)) {
$error_msg = implode('; ', $errors);
header("Location: feedback_form.php?error=" . urlencode($error_msg));
exit;
}
// 获取客户端IP
$ip_address = $_SERVER['REMOTE_ADDR'];
// 防刷验证:同一IP 5分钟内只能留言一次
$database = new Database();
$db = $database->getConnection();
$stmt = $db->prepare("SELECT COUNT(*) FROM feedback
WHERE ip_address = :ip
AND created_at > DATE_SUB(NOW(), INTERVAL 5 MINUTE)");
$stmt->bindParam(':ip', $ip_address);
$stmt->execute();
$recent_count = $stmt->fetchColumn();
if ($recent_count > 0) {
header('Location: feedback_form.php?error=操作太频繁,请5分钟后再试');
exit;
}
try {
$sql = "INSERT INTO feedback (name, email, phone, category, title, content, ip_address, created_at)
VALUES (:name, :email, :phone, :category, :title, :content, :ip_address, NOW())";
$stmt = $db->prepare($sql);
$stmt->bindParam(':name', $name);
$stmt->bindParam(':email', $email);
$stmt->bindParam(':phone', $phone);
$stmt->bindParam(':category', $category);
$stmt->bindParam(':title', $title);
$stmt->bindParam(':content', $content);
$stmt->bindParam(':ip_address', $ip_address);
$stmt->execute();
// 可选:发送通知邮件
// sendNotificationEmail($title, $content);
header('Location: feedback_form.php?success=1');
} catch(PDOException $e) {
header('Location: feedback_form.php?error=系统错误,请稍后重试');
}
?>
留言列表展示
feedback_list.php:
<?php
require_once 'config/database.php';
$page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
$perPage = 10;
$offset = ($page - 1) * $perPage;
$database = new Database();
$db = $database->getConnection();
// 查询总记录数
$countStmt = $db->query("SELECT COUNT(*) FROM feedback WHERE status = 1");
$totalRecords = $countStmt->fetchColumn();
$totalPages = ceil($totalRecords / $perPage);
// 查询当前页数据
$sql = "SELECT * FROM feedback
WHERE status = 1
ORDER BY created_at DESC
LIMIT :limit OFFSET :offset";
$stmt = $db->prepare($sql);
$stmt->bindParam(':limit', $perPage, PDO::PARAM_INT);
$stmt->bindParam(':offset', $offset, PDO::PARAM_INT);
$stmt->execute();
$feedbacks = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">留言列表</title>
<style>
.feedback-list {
max-width: 800px;
margin: 50px auto;
}
.feedback-item {
border: 1px solid #ddd;
margin-bottom: 20px;
padding: 15px;
border-radius: 5px;
}
.feedback-header {
display: flex;
justify-content: space-between;
margin-bottom: 10px;
color: #666;
}
.feedback-title {
font-size: 18px;
font-weight: bold;
margin-bottom: 10px;
}
.feedback-content {
line-height: 1.6;
margin-bottom: 10px;
}
.feedback-reply {
background-color: #f8f9fa;
padding: 10px;
border-left: 3px solid #007bff;
margin-top: 10px;
}
.pagination {
text-align: center;
margin-top: 20px;
}
.pagination a {
display: inline-block;
padding: 5px 10px;
margin: 0 2px;
border: 1px solid #ddd;
text-decoration: none;
color: #333;
}
.pagination a.active {
background-color: #007bff;
color: white;
border-color: #007bff;
}
</style>
</head>
<body>
<div class="feedback-list">
<h2>留言列表</h2>
<?php if (empty($feedbacks)): ?>
<p>暂无留言</p>
<?php else: ?>
<?php foreach ($feedbacks as $feedback): ?>
<div class="feedback-item">
<div class="feedback-header">
<span>留言人:<?php echo htmlspecialchars($feedback['name']); ?></span>
<span>类型:<?php echo htmlspecialchars($feedback['category']); ?></span>
<span><?php echo date('Y-m-d H:i', strtotime($feedback['created_at'])); ?></span>
</div>
<div class="feedback-title">
<?php echo htmlspecialchars($feedback['title']); ?>
</div>
<div class="feedback-content">
<?php echo nl2br(htmlspecialchars($feedback['content'])); ?>
</div>
<?php if (!empty($feedback['reply'])): ?>
<div class="feedback-reply">
<strong>管理员回复:</strong>
<?php echo nl2br(htmlspecialchars($feedback['reply'])); ?>
</div>
<?php endif; ?>
</div>
<?php endforeach; ?>
<div class="pagination">
<?php if ($page > 1): ?>
<a href="?page=<?php echo $page - 1; ?>">上一页</a>
<?php endif; ?>
<?php for ($i = 1; $i <= $totalPages; $i++): ?>
<a href="?page=<?php echo $i; ?>"
class="<?php echo $i == $page ? 'active' : ''; ?>">
<?php echo $i; ?>
</a>
<?php endfor; ?>
<?php if ($page < $totalPages): ?>
<a href="?page=<?php echo $page + 1; ?>">下一页</a>
<?php endif; ?>
</div>
<?php endif; ?>
</div>
</body>
</html>
管理员后台回复
admin_reply.php(需要登录验证):
<?php
// 需要管理员登录验证
require_once 'config/database.php';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$id = (int)$_POST['id'];
$reply = trim($_POST['reply']);
$database = new Database();
$db = $database->getConnection();
$sql = "UPDATE feedback
SET reply = :reply,
status = 1,
updated_at = NOW()
WHERE id = :id";
$stmt = $db->prepare($sql);
$stmt->bindParam(':reply', $reply);
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
if ($stmt->execute()) {
header('Location: admin_feedback_list.php?success=1');
} else {
header('Location: admin_feedback_list.php?error=1');
}
}
?>
关键安全措施
// 1. CSRF防护
session_start();
$token = bin2hex(random_bytes(32));
$_SESSION['csrf_token'] = $token;
// 表单中添加:<input type="hidden" name="csrf_token" value="<?php echo $token; ?>">
// 提交时验证
// 2. XSS防护
$safe_content = htmlspecialchars($content, ENT_QUOTES, 'UTF-8');
// 3. SQL注入防护 - 使用预处理语句(已实现)
// 4. 频次限制
file_put_contents('rate_limit.log', date('Y-m-d H:i:s') . " - IP: $ip_address\n", FILE_APPEND);
可选功能扩展
- 邮件通知:提交留言后发送邮件通知管理员
- 验证码:添加图形验证码或Google reCAPTCHA
- 附件上传:允许上传图片或文件
- 状态标记:管理员标记已处理/未处理
- 搜索筛选:按时间、类型、状态筛选
- API接口:提供RESTful API供前端调用
这个完整的留言反馈系统包含了数据库设计、前端展示、后端处理和安全管理,你可以根据需要调整样式和功能,建议在实际部署时添加更多的安全措施,如内容过滤、防XSS攻击等。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播