mysql菜鸟教程

专栏导航

18.4 实战:开发简单的学生管理系统

18.4 实战:开发简单的学生管理系统

本节我们将从零开始,利用 PHP 和 MySQL 构建一个简单的学生管理系统。系统虽小,但覆盖了 Web 开发的核心环节:数据库设计、后端逻辑处理、前后端数据交互。完成本项目后,你将具备开发基础信息管理系统的能力。

一、功能需求

  • 展示所有学生列表

  • 添加新学生

  • 修改已有学生信息

  • 删除学生记录

  • 按姓名或学号搜索学生

二、环境准备

  • PHP 7.4+(推荐 8.0+)

  • MySQL 5.7+ 或 MariaDB

  • Web 服务器(Apache / Nginx),这里以 Apache 为例

  • 代码编辑器(VS Code 等)

将项目放在 Web 服务器的根目录下,例如 student_manage 文件夹。

三、数据库设计

创建一个名为 student_db 的数据库,并在其中建立 students 表:

CREATE DATABASE IF NOT EXISTS student_db 
DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE student_db;
CREATE TABLE students (
    id INT AUTO_INCREMENT PRIMARY KEY,
    student_id VARCHAR(20) NOT NULL UNIQUE COMMENT '学号',
    name VARCHAR(50) NOT NULL COMMENT '姓名',
    gender ENUM('男','女') NOT NULL COMMENT '性别',
    age TINYINT UNSIGNED NOT NULL COMMENT '年龄',
    class VARCHAR(50) COMMENT '班级',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

插入几条测试数据方便调试:

INSERT INTO students (student_id, name, gender, age, class)
 VALUES('2024001', '张三', '男', 20, '计算机科学1班'),
 ('2024002', '李四', '女', 21, '计算机科学2班'),
 ('2024003', '王五', '男', 19, '软件工程1班');

四、项目结构

student_manage/
├── config.php          # 数据库配置与连接
├── index.php           # 学生列表与搜索(主页面)
├── add.php             # 添加学生页面(表单+处理)
├── edit.php            # 编辑学生页面
├── delete.php          # 删除学生逻辑
└── style.css           # 简单样式

第一步:数据库连接配置文件

config.php 负责连接 MySQL,并提供获取连接的函数。使用 mysqli 扩展(面向过程风格,易于理解)。

<?php
// config.php
define('DB_HOST', 'localhost');
define('DB_USER', 'root');
define('DB_PASS', '');          // 根据实际环境填写密码
define('DB_NAME', 'student_db');
// 创建连接
$conn = mysqli_connect(DB_HOST, DB_USER, DB_PASS, DB_NAME);
// 检查连接
if (!$conn) {
    die("数据库连接失败: " . mysqli_connect_error());
}
// 设置字符集
mysqli_set_charset($conn, "utf8mb4");


其他页面只需 require_once 'config.php'; 即可使用 $conn

第二步:学生列表与搜索(index.php)

主页面展示所有学生,提供搜索框、添加按钮,每条记录有编辑和删除操作。支持按学号或姓名模糊查询。

<?php
require_once 'config.php';
// 处理搜索
$search = $_GET['search'] ?? '';
$where = '';
if (!empty($search)) {
    // 转义防注入
    $search_esc = mysqli_real_escape_string($conn, $search);
    $where = "WHERE student_id LIKE '%{$search_esc}%' "
    +"OR name LIKE '%{$search_esc}%'";
}
$sql = "SELECT * FROM students {$where} ORDER BY id DESC";
$result = mysqli_query($conn, $sql);
?>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>学生管理系统</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
<div>
    <h1>学生管理系统</h1>
    <div>
        <form action="index.php" method="get">
            <input type="text" name="search" placeholder="输入学号或姓名搜索"
             value="<?php echo htmlspecialchars($search); ?>">
            <button type="submit">搜索</button>
            <a href="index.php">显示全部</a>
        </form>
        <a href="add.php">添加新学生</a>
    </div>
    <table border="1" cellpadding="8" cellspacing="0">
        <thead>
            <tr>
                <th>ID</th>
                <th>学号</th>
                <th>姓名</th>
                <th>性别</th>
                <th>年龄</th>
                <th>班级</th>
                <th>操作</th>
            </tr>
        </thead>
        <tbody>
        <?php if (mysqli_num_rows($result) > 0): ?>
            <?php while ($row = mysqli_fetch_assoc($result)): ?>
            <tr>
                <td><?php echo $row['id']; ?></td>
                <td><?php echo htmlspecialchars($row['student_id']); ?></td>
                <td><?php echo htmlspecialchars($row['name']); ?></td>
                <td><?php echo $row['gender']; ?></td>
                <td><?php echo $row['age']; ?></td>
                <td><?php echo htmlspecialchars($row['class']); ?></td>
                <td>
                    <a href="edit.php?id=<?php echo $row['id']; ?>">编辑</a>
                    <a href="delete.php?id=<?php echo $row['id']; ?>" 
                    onclick="return confirm('确认删除该学生吗?');">删除</a>
                </td>
            </tr>
            <?php endwhile; ?>
        <?php else: ?>
            <tr><td colspan="7">暂无学生数据</td></tr>
        <?php endif; ?>
        </tbody>
    </table>
</div>
</body>
</html>


要点:

  • 使用 mysqli_real_escape_string 防止 SQL 注入。

  • 输出时用 htmlspecialchars 避免 XSS 攻击。

  • 删除前用 JavaScript 确认,防止误操作。

第三步:添加学生(add.php)

添加页面同时展示表单和处理提交。使用 POST-Redirect-GET 模式避免重复提交,但简单系统直接在同文件判断即可。

<?php
require_once 'config.php';
$error = '';
$success = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $student_id = trim($_POST['student_id'] ?? '');
    $name       = trim($_POST['name'] ?? '');
    $gender     = $_POST['gender'] ?? '';
    $age        = intval($_POST['age'] ?? 0);
    $class      = trim($_POST['class'] ?? '');
    // 简单验证
    if ($student_id === '' || $name === '' || $gender === '' || $age <= 0) {
        $error = '请完整填写所有必填字段。';
    } else {
        // 检查学号唯一性
        $check_sql = "SELECT id FROM students WHERE student_id = ?";
        $stmt = mysqli_prepare($conn, $check_sql);
        mysqli_stmt_bind_param($stmt, "s", $student_id);
        mysqli_stmt_execute($stmt);
        mysqli_stmt_store_result($stmt);
        if (mysqli_stmt_num_rows($stmt) > 0) {
            $error = '该学号已存在,请更换。';
        } else {
            // 插入数据
            $insert_sql = "INSERT INTO students "+
            "(student_id, name, gender, age, class) VALUES (?, ?, ?, ?, ?)";
            $stmt_insert = mysqli_prepare($conn, $insert_sql);
            mysqli_stmt_bind_param($stmt_insert, 
            "sssis", $student_id, $name, $gender, $age, $class);
            if (mysqli_stmt_execute($stmt_insert)) {
                $success = '学生添加成功!';
                // 可重定向到首页,这里直接显示成功消息
            } else {
                $error = '添加失败: ' . mysqli_error($conn);
            }
        }
    }
}
?>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>添加学生</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
<div>
    <h1>添加新学生</h1>
    <?php if ($error): ?>
        <p><?php echo $error; ?></p>
    <?php endif; ?>
    <?php if ($success): ?>
        <p><?php echo $success; ?> <a href="index.php">返回列表</a></p>
    <?php else: ?>
    <form method="post" action="add.php">
        <label>学号:<input type="text" name="student_id" required></label><br>
        <label>姓名:<input type="text" name="name" required></label><br>
        <label>性别:
            <select name="gender" required>
                <option value="">请选择</option>
                <option value="男">男</option>
                <option value="女">女</option>
            </select>
        </label><br>
        <label>年龄:<input type="number" name="age" min="1" max="150" required>
        </label><br>
        <label>班级:<input type="text" name="class"></label><br>
        <button type="submit">添加</button>
        <a href="index.php">取消</a>
    </form>
    <?php endif; ?>
</div>
</body>
</html>


此处使用预处理语句彻底杜绝 SQL 注入。

第四步:编辑学生(edit.php)

编辑功能先根据 ID 获取原有数据填充表单,提交时执行 UPDATE。

<?php
require_once 'config.php';
$id = $_GET['id'] ?? 0;
$id = intval($id);
// 获取原有数据
$sql = "SELECT * FROM students WHERE id = ?";
$stmt = mysqli_prepare($conn, $sql);
mysqli_stmt_bind_param($stmt, "i", $id);
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
$student = mysqli_fetch_assoc($result);
if (!$student) {
    die("学生不存在");
}
$error = '';
$success = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $student_id = trim($_POST['student_id'] ?? '');
    $name       = trim($_POST['name'] ?? '');
    $gender     = $_POST['gender'] ?? '';
    $age        = intval($_POST['age'] ?? 0);
    $class      = trim($_POST['class'] ?? '');

    if ($student_id === '' || $name === '' || $gender === '' || $age <= 0) {
        $error = '请完整填写所有必填字段。';
    } else {
        // 检查学号是否与其他记录冲突
        $check_sql = "SELECT id FROM students WHERE student_id = ? AND id != ?";
        $stmt_check = mysqli_prepare($conn, $check_sql);
        mysqli_stmt_bind_param($stmt_check, "si", $student_id, $id);
        mysqli_stmt_execute($stmt_check);
        mysqli_stmt_store_result($stmt_check);
        if (mysqli_stmt_num_rows($stmt_check) > 0) {
            $error = '该学号已被其他学生使用。';
        } else {
            $update_sql = "UPDATE students SET student_id=?, name=?, gender=?, "+
            "age=?, class=? WHERE id=?";
            $stmt_update = mysqli_prepare($conn, $update_sql);
            mysqli_stmt_bind_param($stmt_update, "sssisi", $student_id, $name, $gender,
             $age, $class, $id);
            if (mysqli_stmt_execute($stmt_update)) {
                $success = '学生信息更新成功!';
                // 重新获取更新后的数据
                $student['student_id'] = $student_id;
                $student['name'] = $name;
                $student['gender'] = $gender;
                $student['age'] = $age;
                $student['class'] = $class;
            } else {
                $error = '更新失败: ' . mysqli_error($conn);
            }
        }
    }}?><!DOCTYPE html><html lang="zh-CN"><head>
    <meta charset="UTF-8">
    <title>编辑学生</title>
    <link rel="stylesheet" href="style.css"></head><body><div class="container">
    <h1>编辑学生信息</h1>
    <?php if ($error): ?>
        <p class="error"><?php echo $error; ?></p>
    <?php endif; ?>
    <?php if ($success): ?>
        <p class="success"><?php echo $success; ?> <a href="index.php">返回列表</a></p>
    <?php endif; ?>
    <form method="post" action="edit.php?id=<?php echo $id; ?>">
        <label>学号:<input type="text" name="student_id" value="<?php echo htmlspecialchars($student['student_id']); ?>" required></label><br>
        <label>姓名:<input type="text" name="name" value="<?php echo htmlspecialchars($student['name']); ?>" required></label><br>
        <label>性别:            <select name="gender" required>
                <option value="男" <?php if($student['gender']==='男') echo 'selected'; ?>>男</option>
                <option value="女" <?php if($student['gender']==='女') echo 'selected'; ?>>女</option>
            </select>
        </label><br>
        <label>年龄:<input type="number" name="age" value="<?php echo $student['age']; ?>" min="1" max="150" required></label><br>
        <label>班级:<input type="text" name="class" value="<?php echo htmlspecialchars($student['class']); ?>"></label><br>
        <button type="submit">保存修改</button>
        <a href="index.php">取消</a>
    </form></div></body></html>

第五步:删除学生(delete.php)

删除操作无需界面,直接处理 GET 参数,执行 DELETE 后重定向。

<?php
require_once 'config.php';
$id = $_GET['id'] ?? 0;
$id = intval($id);
if ($id > 0) {
    $sql = "DELETE FROM students WHERE id = ?";
    $stmt = mysqli_prepare($conn, $sql);
    mysqli_stmt_bind_param($stmt, "i", $id);
    mysqli_stmt_execute($stmt);
}
// 重定向回列表页
header("Location: index.php");exit;

简单样式(style.css)

使界面更清爽:

body {
    font-family: "Microsoft YaHei", sans-serif;
    background: #f5f7fa;
    margin: 0;
    padding: 20px;
}
.container {
    width: 900px;
    margin: 0 auto;
    background: #fff;
    padding: 20px 30px;
    border-radius: 8px;
    box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
h1 {
    text-align: center;
    color: #333;
}
.toolbar {
    display: flex;
    justify-content: space-between;
    margin-bottom: 15px;}.search-form input {
    padding: 6px;
    width: 240px;}table {
    width: 100%;
    border-collapse: collapse;}th {
    background: #4a90e2;
    color: white;}td, th {
    text-align: center;}a {
    text-decoration: none;
    margin: 0 5px;}.btn-add, .btn-reset {
    padding: 8px 15px;
    background: #4a90e2;
    color: #fff;
    border-radius: 4px;}.error {
    color: #d9534f;
    background: #f2dede;
    padding: 8px;
    border-radius: 4px;}.success {
    color: #3c763d;
    background: #dff0d8;
    padding: 8px;
    border-radius: 4px;}form label {
    display: block;
    margin: 12px 0;}form input, form select {
    padding: 6px;
    width: 260px;
    margin-left: 8px;}button {
    padding: 8px 20px;
    cursor: pointer;}

运行与测试

  1. 启动 MySQL 和 Apache,导入数据库结构。

  2. 修改 config.php 中的数据库连接信息。

  3. 浏览器访问 http://localhost/student_manage/index.php

  4. 尝试搜索、添加、编辑、删除,观察功能是否正常。

安全与优化建议

  • 密码保护:实际项目中不应将数据库密码直接写在配置文件中,可使用环境变量。

  • 输入验证:前后端双重验证,年龄确保正整数。

  • CSRF 防护:为表单添加 token 防止跨站请求伪造。

  • 分页:当数据量大时,应增加分页功能,避免一次性加载所有记录。

  • 面向对象与框架:本实例采用面向过程,便于理解基础原理。生产环境可考虑使用 PDO、MVC 框架(如 Laravel、ThinkPHP)以提高开发效率和安全性。


所有评论

关于我 备案号:蜀ICP备2023042032号-1