Appearance
14.1 实战 1:简单留言本(表单 + 数据库 + 展示)
本章节将实现一个简单的留言本系统,包括表单提交、数据库存储和留言展示功能。
项目结构
simple-message-board/
├── db.php # 数据库连接文件
├── index.php # 留言展示页面
├── add_message.php # 留言提交处理
└── css/
└── style.css # 样式文件1. 数据库配置
创建 db.php 文件,用于数据库连接:
php
<?php
// db.php
function getDbConnection() {
$servername = "localhost";
$username = "root";
$password = "";
$dbname = "php_tutorial";
// 创建连接
$conn = new mysqli($servername, $username, $password, $dbname);
// 检查连接
if ($conn->connect_error) {
die("连接失败: " . $conn->connect_error);
}
// 设置字符集
$conn->set_charset("utf8mb4");
return $conn;
}
?>2. 数据库表结构
创建 messages 表:
sql
CREATE TABLE messages (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
email VARCHAR(100) NOT NULL,
message TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);3. 样式文件
创建 css/style.css 文件:
css
/* style.css */
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: Arial, sans-serif;
line-height: 1.6;
color: #333;
background-color: #f4f4f4;
}
.container {
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
h1 {
text-align: center;
color: #333;
margin-bottom: 30px;
}
.message-form {
background-color: #fff;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
margin-bottom: 30px;
}
.form-group {
margin-bottom: 15px;
}
label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}
input[type="text"],
input[type="email"],
textarea {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 16px;
}
textarea {
height: 150px;
resize: vertical;
}
button[type="submit"] {
background-color: #4CAF50;
color: white;
padding: 10px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
}
button[type="submit"]:hover {
background-color: #45a049;
}
.messages {
background-color: #fff;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.message {
border-bottom: 1px solid #eee;
padding: 15px 0;
}
.message:last-child {
border-bottom: none;
}
.message-header {
display: flex;
justify-content: space-between;
margin-bottom: 10px;
}
.message-name {
font-weight: bold;
color: #333;
}
.message-time {
font-size: 12px;
color: #999;
}
.message-content {
color: #666;
line-height: 1.5;
}
.error {
background-color: #f8d7da;
color: #721c24;
padding: 10px;
border-radius: 4px;
margin-bottom: 15px;
border: 1px solid #f5c6cb;
}
.success {
background-color: #d4edda;
color: #155724;
padding: 10px;
border-radius: 4px;
margin-bottom: 15px;
border: 1px solid #c3e6cb;
}4. 留言展示页面
创建 index.php 文件:
php
<?php
// index.php
require_once 'db.php';
$conn = getDbConnection();
// 获取留言列表
$sql = "SELECT * FROM messages ORDER BY created_at DESC";
$result = $conn->query($sql);
$messages = [];
if ($result->num_rows > 0) {
while ($row = $result->fetch_assoc()) {
$messages[] = $row;
}
}
$conn->close();
?>
<!DOCTYPE html>
<html>
<head>
<title>简单留言本</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<div class="container">
<h1>简单留言本</h1>
<!-- 留言表单 -->
<div class="message-form">
<h2>发表留言</h2>
<?php if (isset($_GET['error'])): ?>
<div class="error"><?php echo $_GET['error']; ?></div>
<?php endif; ?>
<?php if (isset($_GET['success'])): ?>
<div class="success"><?php echo $_GET['success']; ?></div>
<?php endif; ?>
<form action="add_message.php" method="post">
<div class="form-group">
<label>姓名: <input type="text" name="name" required></label>
</div>
<div class="form-group">
<label>邮箱: <input type="email" name="email" required></label>
</div>
<div class="form-group">
<label>留言: <textarea name="message" required></textarea></label>
</div>
<button type="submit" name="submit">发表留言</button>
</form>
</div>
<!-- 留言列表 -->
<div class="messages">
<h2>留言列表</h2>
<?php if (empty($messages)): ?>
<p>暂无留言,快来发表第一条留言吧!</p>
<?php else: ?>
<?php foreach ($messages as $message): ?>
<div class="message">
<div class="message-header">
<span class="message-name"><?php echo htmlspecialchars($message['name']); ?></span>
<span class="message-time"><?php echo $message['created_at']; ?></span>
</div>
<div class="message-content"><?php echo nl2br(htmlspecialchars($message['message'])); ?></div>
</div>
<?php endforeach; ?>
<?php endif; ?>
</div>
</div>
</body>
</html>5. 留言提交处理
创建 add_message.php 文件:
php
<?php
// add_message.php
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['submit'])) {
require_once 'db.php';
$conn = getDbConnection();
// 获取表单数据
$name = $_POST['name'];
$email = $_POST['email'];
$message = $_POST['message'];
// 验证数据
if (empty($name) || empty($email) || empty($message)) {
header('Location: index.php?error=所有字段都不能为空');
exit;
}
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
header('Location: index.php?error=邮箱格式不正确');
exit;
}
// 准备 SQL 语句
$stmt = $conn->prepare("INSERT INTO messages (name, email, message) VALUES (?, ?, ?)");
$stmt->bind_param("sss", $name, $email, $message);
// 执行 SQL 语句
if ($stmt->execute()) {
header('Location: index.php?success=留言发表成功');
exit;
} else {
header('Location: index.php?error=留言发表失败,请重试');
exit;
}
$stmt->close();
$conn->close();
} else {
header('Location: index.php');
exit;
}
?>6. 运行项目
- 确保数据库已创建并创建了
messages表 - 启动本地服务器
- 访问
http://localhost/simple-message-board/index.php - 填写表单并发表留言
- 查看留言列表
7. 功能扩展
1. 添加分页功能
修改 index.php 文件,添加分页功能:
php
<?php
// index.php
require_once 'db.php';
$conn = getDbConnection();
// 分页设置
$page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
$perPage = 5;
$offset = ($page - 1) * $perPage;
// 获取留言总数
$sql = "SELECT COUNT(*) as total FROM messages";
$result = $conn->query($sql);
$row = $result->fetch_assoc();
$totalMessages = $row['total'];
$totalPages = ceil($totalMessages / $perPage);
// 获取留言列表
$sql = "SELECT * FROM messages ORDER BY created_at DESC LIMIT ? OFFSET ?";
$stmt = $conn->prepare($sql);
$stmt->bind_param("ii", $perPage, $offset);
$stmt->execute();
$result = $stmt->get_result();
$messages = [];
if ($result->num_rows > 0) {
while ($row = $result->fetch_assoc()) {
$messages[] = $row;
}
}
$stmt->close();
$conn->close();
?>
<!-- 在留言列表下方添加分页 -->
<?php if ($totalPages > 1): ?>
<div class="pagination" style="margin-top: 20px; text-align: center;">
<?php if ($page > 1): ?>
<a href="index.php?page=<?php echo $page - 1; ?>" style="margin: 0 5px; text-decoration: none; color: #4CAF50;">上一页</a>
<?php endif; ?>
<?php for ($i = 1; $i <= $totalPages; $i++): ?>
<a href="index.php?page=<?php echo $i; ?>" style="margin: 0 5px; text-decoration: none; color: <?php echo $i == $page ? '#4CAF50' : '#333'; ?>;">
<?php echo $i; ?>
</a>
<?php endfor; ?>
<?php if ($page < $totalPages): ?>
<a href="index.php?page=<?php echo $page + 1; ?>" style="margin: 0 5px; text-decoration: none; color: #4CAF50;">下一页</a>
<?php endif; ?>
</div>
<?php endif; ?>2. 添加留言删除功能
修改 index.php 文件,添加删除按钮:
php
<!-- 在留言内容下方添加删除按钮 -->
<div class="message-actions" style="margin-top: 10px;">
<a href="delete_message.php?id=<?php echo $message['id']; ?>" style="color: #dc3545; text-decoration: none; font-size: 14px;" onclick="return confirm('确定要删除这条留言吗?');">删除</a>
</div>创建 delete_message.php 文件:
php
<?php
// delete_message.php
if (isset($_GET['id'])) {
$messageId = $_GET['id'];
require_once 'db.php';
$conn = getDbConnection();
// 准备 SQL 语句
$stmt = $conn->prepare("DELETE FROM messages WHERE id = ?");
$stmt->bind_param("i", $messageId);
// 执行 SQL 语句
if ($stmt->execute()) {
header('Location: index.php?success=留言删除成功');
exit;
} else {
header('Location: index.php?error=留言删除失败,请重试');
exit;
}
$stmt->close();
$conn->close();
} else {
header('Location: index.php');
exit;
}
?>3. 添加留言编辑功能
修改 index.php 文件,添加编辑按钮:
php
<!-- 在留言内容下方添加编辑按钮 -->
<div class="message-actions" style="margin-top: 10px;">
<a href="edit_message.php?id=<?php echo $message['id']; ?>" style="color: #007bff; text-decoration: none; font-size: 14px; margin-right: 10px;">编辑</a>
<a href="delete_message.php?id=<?php echo $message['id']; ?>" style="color: #dc3545; text-decoration: none; font-size: 14px;" onclick="return confirm('确定要删除这条留言吗?');">删除</a>
</div>创建 edit_message.php 文件:
php
<?php
// edit_message.php
if (!isset($_GET['id'])) {
header('Location: index.php');
exit;
}
$messageId = $_GET['id'];
require_once 'db.php';
$conn = getDbConnection();
// 获取留言信息
$stmt = $conn->prepare("SELECT * FROM messages WHERE id = ?");
$stmt->bind_param("i", $messageId);
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows === 0) {
header('Location: index.php?error=留言不存在');
exit;
}
$message = $result->fetch_assoc();
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['submit'])) {
// 获取表单数据
$name = $_POST['name'];
$email = $_POST['email'];
$messageContent = $_POST['message'];
// 验证数据
if (empty($name) || empty($email) || empty($messageContent)) {
header('Location: edit_message.php?id=' . $messageId . '&error=所有字段都不能为空');
exit;
}
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
header('Location: edit_message.php?id=' . $messageId . '&error=邮箱格式不正确');
exit;
}
// 准备 SQL 语句
$stmt = $conn->prepare("UPDATE messages SET name = ?, email = ?, message = ? WHERE id = ?");
$stmt->bind_param("sssi", $name, $email, $messageContent, $messageId);
// 执行 SQL 语句
if ($stmt->execute()) {
header('Location: index.php?success=留言编辑成功');
exit;
} else {
header('Location: edit_message.php?id=' . $messageId . '&error=留言编辑失败,请重试');
exit;
}
}
$stmt->close();
$conn->close();
?>
<!DOCTYPE html>
<html>
<head>
<title>编辑留言</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<div class="container">
<h1>编辑留言</h1>
<div class="message-form">
<?php if (isset($_GET['error'])): ?>
<div class="error"><?php echo $_GET['error']; ?></div>
<?php endif; ?>
<form action="" method="post">
<div class="form-group">
<label>姓名: <input type="text" name="name" value="<?php echo htmlspecialchars($message['name']); ?>" required></label>
</div>
<div class="form-group">
<label>邮箱: <input type="email" name="email" value="<?php echo htmlspecialchars($message['email']); ?>" required></label>
</div>
<div class="form-group">
<label>留言: <textarea name="message" required><?php echo htmlspecialchars($message['message']); ?></textarea></label>
</div>
<button type="submit" name="submit">保存修改</button>
<a href="index.php" style="margin-left: 10px; text-decoration: none; color: #666;">取消</a>
</form>
</div>
</div>
</body>
</html>8. 注意事项
安全性:
- 使用
htmlspecialchars防止 XSS 攻击 - 使用预处理语句防止 SQL 注入
- 验证用户输入
- 使用
性能:
- 使用分页减少数据传输
- 优化数据库查询
用户体验:
- 提供清晰的错误提示
- 显示操作成功的反馈
- 确认删除操作
兼容性:
- 确保在不同浏览器中正常显示
- 响应式设计,适配不同屏幕尺寸
练习
- 实现完整的简单留言本系统
- 添加分页功能
- 添加留言删除功能
- 添加留言编辑功能
- 优化用户界面和体验
