第十三章-PHP MySQL扩展

第十三章-PHP与MySQL

一,连接数据库

1. 使用 MySQLi(面向对象方式)

php 复制代码
<?php
// 数据库参数
$host = 'localhost';
$username = 'root';
$password = '';
$database = 'test_db';

// 创建连接
$conn = new mysqli($host, $username, $password, $database);

// 检查连接是否成功
if ($conn->connect_error) {
    die("连接失败: " . $conn->connect_error);
}

echo "数据库连接成功!";

// 执行查询示例
$sql = "SELECT id, name FROM users";
$result = $conn->query($sql);

if ($result->num_rows > 0) {
    while ($row = $result->fetch_assoc()) {
        echo "ID: " . $row["id"] . ",姓名: " . $row["name"];
    }
} else {
    echo "没有查询到数据";
}

// 关闭连接
$conn->close();
?>

2. 使用 MySQLi(过程化方式)

php 复制代码
<?php
$host = 'localhost';
$username = 'root';
$password = '';
$database = 'test_db';

// 创建连接
$conn = mysqli_connect($host, $username, $password, $database);

// 检查连接
if (!$conn) {
    die("连接失败: " . mysqli_connect_error());
}

echo "数据库连接成功!";

// 执行查询示例
$sql = "SELECT id, name FROM users";
$result = mysqli_query($conn, $sql);

if (mysqli_num_rows($result) > 0) {
    while ($row = mysqli_fetch_assoc($result)) {
        echo "ID: " . $row["id"] . ",姓名: " . $row["name"];
    }
}

// 关闭连接
mysqli_close($conn);
?>

3. 使用 PDO(支持多种数据库)

php 复制代码
<?php
$host = 'localhost';
$database = 'test_db';
$username = 'root';
$password = '';

try {
    // 创建 PDO 连接
    $conn = new PDO("mysql:host=$host;dbname=$database", $username, $password);
    
    // 设置错误模式为异常捕获
    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    echo "数据库连接成功!";

    // 执行查询示例(使用预处理语句防注入)
    $sql = "SELECT id, name FROM users";
    $stmt = $conn->prepare($sql);
    $stmt->execute();

    // 获取结果
    $result = $stmt->fetchAll(PDO::FETCH_ASSOC);
    foreach ($result as $row) {
        echo "ID: " . $row["id"] . ",姓名: " . $row["name"];
    }

} catch (PDOException $e) {
    die("连接失败: " . $e->getMessage());
}

// 关闭连接(PDO 自动管理)
$conn = null;
?>

关键注意事项

  1. 防止 SQL 注入

    • 使用预处理语句(如 $stmt->prepare() + bindParamexecute([参数]))。

    • 示例(PDO 预处理):

      php 复制代码
      $stmt = $conn->prepare("INSERT INTO users (name, email) VALUES (:name, :email)");
      $stmt->bindParam(':name', $name);
      $stmt->bindParam(':email', $email);
      $stmt->execute();
  2. 错误处理

    • MySQLi 使用 $conn->connect_errormysqli_connect_error()
    • PDO 使用异常捕获(try...catch + setAttribute)。
  3. 关闭连接

    • MySQLi:$conn->close()mysqli_close($conn)
    • PDO:$conn = null

常见问题

  • 连接失败可能原因

    1. 用户名/密码错误
    2. 数据库未启动
    3. 防火墙阻止连接
    4. PHP 未启用 MySQLi/PDO 扩展(检查 php.ini
  • 启用扩展

    php.ini 中取消注释:

    ini 复制代码
    ;extension=mysqli
    ;extension=pdo_mysql

    重启 Web 服务器生效。


二、增删改查操作实现

1. 增加数据(Create)

MySQLi 预处理插入
复制代码
// 准备预处理语句
$stmt = $conn->prepare("INSERT INTO users (name, email) VALUES (?, ?)");
$stmt->bind_param("ss", $name, $email); // "ss" 表示两个字符串参数

// 设置参数并执行
$name = "张三";
$email = "zhangsan@example.com";
$stmt->execute();

echo "插入成功,ID: " . $stmt->insert_id;
$stmt->close();
PDO 预处理插入
php 复制代码
try {
    $sql = "INSERT INTO users (name, email) VALUES (:name, :email)";
    $stmt = $conn->prepare($sql);
    
    // 绑定参数并执行
    $stmt->execute([
        ':name' => '李四',
        ':email' => 'lisi@example.com'
    ]);
    
    echo "插入成功,ID: " . $conn->lastInsertId();
} catch (PDOException $e) {
    echo "错误: " . $e->getMessage();
}

2. 查询数据(Read)

MySQLi 查询并遍历结果
php 复制代码
$sql = "SELECT id, name, email FROM users";
$result = $conn->query($sql);

if ($result->num_rows > 0) {
    while ($row = $result->fetch_assoc()) {
        echo "ID: {$row['id']}, 姓名: {$row['name']}, 邮箱: {$row['email']}<br>";
    }
} else {
    echo "没有数据";
}
$result->free(); // 释放结果集
PDO 查询并遍历结果
php 复制代码
try {
    $stmt = $conn->query("SELECT id, name, email FROM users");
    $results = $stmt->fetchAll(PDO::FETCH_ASSOC);
    
    foreach ($results as $row) {
        echo "ID: {$row['id']}, 姓名: {$row['name']}, 邮箱: {$row['email']}<br>";
    }
} catch (PDOException $e) {
    echo "错误: " . $e->getMessage();
}

3. 更新数据(Update)

MySQLi 预处理更新
php 复制代码
$stmt = $conn->prepare("UPDATE users SET email = ? WHERE id = ?");
$stmt->bind_param("si", $email, $id); // "si" 表示字符串和整数

$email = "new_email@example.com";
$id = 1;
$stmt->execute();

echo "更新了 {$stmt->affected_rows} 条记录";
$stmt->close();
PDO 预处理更新
php 复制代码
try {
    $sql = "UPDATE users SET email = :email WHERE id = :id";
    $stmt = $conn->prepare($sql);
    $stmt->execute([
        ':email' => 'updated@example.com',
        ':id' => 1
    ]);
    
    echo "更新了 {$stmt->rowCount()} 条记录";
} catch (PDOException $e) {
    echo "错误: " . $e->getMessage();
}

4. 删除数据(Delete)

MySQLi 预处理删除
php 复制代码
$stmt = $conn->prepare("DELETE FROM users WHERE id = ?");
$stmt->bind_param("i", $id); // "i" 表示整数

$id = 2;
$stmt->execute();

echo "删除了 {$stmt->affected_rows} 条记录";
$stmt->close();
PDO 预处理删除
php 复制代码
try {
    $sql = "DELETE FROM users WHERE id = :id";
    $stmt = $conn->prepare($sql);
    $stmt->execute([':id' => 3]);
    
    echo "删除了 {$stmt->rowCount()} 条记录";
} catch (PDOException $e) {
    echo "错误: " . $e->getMessage();
}

5.安全与最佳实践

  1. 始终使用预处理语句

    • 避免 SQL 注入攻击,禁止直接拼接用户输入到 SQL 中。
  2. 错误处理

    • MySQLi 检查 $conn->error,PDO 使用 try...catch 捕获异常。
  3. 关闭连接

    php 复制代码
    // MySQLi
    $conn->close();
    
    // PDO
    $conn = null;
  4. 验证输入数据

    • 使用 filter_var() 验证邮箱、URL 等格式。
    • 检查数值范围(如 $id > 0)。

6.完整流程图

plaintext 复制代码
1. 连接数据库 → 2. 准备SQL语句 → 3. 绑定参数 → 4. 执行操作 → 5. 处理结果 → 6. 关闭连接

7.扩展建议

  • 使用 ORM 框架

    如 Laravel 的 Eloquent 或 Doctrine,简化数据库操作。

  • 事务处理

    对于多个关联操作,使用事务保证数据一致性:

    php 复制代码
    // PDO 事务示例
    $conn->beginTransaction();
    try {
        $conn->exec("UPDATE account SET balance = balance - 100 WHERE id = 1");
        $conn->exec("UPDATE account SET balance = balance + 100 WHERE id = 2");
        $conn->commit();
    } catch (Exception $e) {
        $conn->rollBack();
        echo "事务失败: " . $e->getMessage();
    }

三,网站查询操作

一,OOP 写法

OOP(面向对象编程,Object-Oriented Programming) 是一种程序设计思想和方法,它把数据对数据的操作 组织成对象(Object),通过对象之间的交互来完成程序设计。

OOP 的核心概念
  1. 类(Class)
    • 类是对象的蓝图或模板 ,定义了对象的属性(数据)**和**方法(操作)
    • 比如:"狗"可以是一个类,它有颜色、品种这些属性,还有叫、跑这些方法。
  2. 对象(Object)
    • 对象是类的实例,是具体存在的个体。
    • 比如:"小黑"是一只狗,它是"狗"类的一个对象。
  3. 封装(Encapsulation)
    • 把数据和操作数据的方法打包在一起,对外隐藏内部细节,只暴露必要的接口。
    • 好处是保护数据安全,减少外部干扰。
  4. 继承(Inheritance)
    • 子类可以继承 父类的属性和方法,复用代码 ,还可以扩展或修改已有功能。
    • 比如,"哈士奇"类可以继承"狗"类的基本特性,再加上自己的特性。
  5. 多态(Polymorphism)
    • 同一种方法在不同对象上可以有不同表现
    • 比如,不同动物的"叫"方法,狗叫"汪汪",猫叫"喵喵",但都可以统一调用"叫"这个动作。
php 复制代码
$mysqli = new mysqli('localhost', 'dbuser', 'dbpass', 'dbname');
if ($mysqli->connect_errno) {
    throw new Exception('数据库连接失败:' . $mysqli->connect_error);
}
$mysqli->set_charset('utf8mb4');

$sql = "SELECT id, username, email FROM users WHERE status = 1 AND is_deleted = 0 ORDER BY created_at DESC LIMIT 10";
$result = $mysqli->query($sql);

if (!$result) {
    throw new Exception('查询失败:' . $mysqli->error);
}

$data = [];
while ($row = $result->fetch_assoc()) {
    $data[] = $row;
}
$result->free();

// 返回数据
return $data;
  • 必须判断连接和查询是否成功
  • 必须释放结果集
  • 查询多行,循环 fetch_assoc() 拼到数组里
  • 查询限制条件齐全:WHEREORDER BYLIMIT 都要标准化

二、参数化查询(防SQL注入)

生产环境绝对禁止拼接变量,必须用预处理。

示例:按用户名模糊搜索
php 复制代码
$stmt = $mysqli->prepare("SELECT id, username, email FROM users WHERE username LIKE CONCAT('%', ?, '%') AND status = 1 LIMIT 20");
if (!$stmt) {
    throw new Exception('预处理失败:' . $mysqli->error);
}

$keyword = 'alice'; // 搜索关键词
$stmt->bind_param('s', $keyword);
$stmt->execute();

$result = $stmt->get_result();
$data = [];
while ($row = $result->fetch_assoc()) {
    $data[] = $row;
}
$stmt->close();

return $data;
  • 预处理 (prepare + bind_param) 必须使用
  • 模糊搜索需要 CONCAT('%', ?, '%') 写法
  • 不要用变量直接拼接到 SQL 字符串里

三、查询单条记录

如果只查一行,可以直接用 fetch_assoc() 拿一次。

php 复制代码
php复制编辑$stmt = $mysqli->prepare("SELECT id, username, email FROM users WHERE id = ?");
$stmt->bind_param('i', $user_id);
$stmt->execute();

$result = $stmt->get_result();
$user = $result->fetch_assoc();
$stmt->close();

// 检查是否查到
if (!$user) {
    throw new Exception('用户不存在');
}

return $user;
  • fetch_assoc() 只取一行,后面不用循环
  • 查不到数据时要有异常/提示处理

四、分页查询(带总数)

分页查询是非常常见需求,要返回数据和总数。

php 复制代码
$page = 1;
$page_size = 10;
$offset = ($page - 1) * $page_size;

// 1. 查询数据
$stmt = $mysqli->prepare("SELECT id, username, email FROM users WHERE status = 1 LIMIT ?, ?");
$stmt->bind_param('ii', $offset, $page_size);
$stmt->execute();
$result = $stmt->get_result();
$list = [];
while ($row = $result->fetch_assoc()) {
    $list[] = $row;
}
$stmt->close();

// 2. 查询总条数
$sql_total = "SELECT COUNT(*) AS total FROM users WHERE status = 1";
$res_total = $mysqli->query($sql_total);
$total_row = $res_total->fetch_assoc();
$total = (int)$total_row['total'];
$res_total->free();

// 返回分页结果
return [
    'list'  => $list,
    'total' => $total
];
  • 分页必须返回数据列表 + 总条数
  • 分开两次查询更稳(一次查数据,一次查总数)

五、复杂条件动态查询(实战重点)

有些条件是用户输入的,要动态拼条件,但还要防注入 。常规做法是动态构造 SQL + 参数绑定

php 复制代码
$conditions = [];
$params = [];
$types = '';

// 假设有用户搜索过滤
if (!empty($filter['username'])) {
    $conditions[] = "username LIKE CONCAT('%', ?, '%')";
    $params[] = $filter['username'];
    $types .= 's';
}
if (isset($filter['status'])) {
    $conditions[] = "status = ?";
    $params[] = (int)$filter['status'];
    $types .= 'i';
}

$where = $conditions ? 'WHERE ' . implode(' AND ', $conditions) : '';

$sql = "SELECT id, username, email FROM users $where ORDER BY created_at DESC LIMIT 20";
$stmt = $mysqli->prepare($sql);
if ($params) {
    $stmt->bind_param($types, ...$params);
}
$stmt->execute();
$result = $stmt->get_result();

$data = [];
while ($row = $result->fetch_assoc()) {
    $data[] = $row;
}
$stmt->close();

return $data;
  • 拼接 SQL 时 条件动态组装,值用绑定
  • 类型字符串 $types 也要跟着参数增长
  • 防止 SQL 注入,同时又灵活

总结

方面 要点
查询数据 query 或 prepare + get_result
查询多行 while(fetch_assoc)
查询单行 fetch_assoc 直接用
分页查询 两次查询:数据和总数分开
防SQL注入 预处理 + bind_param
动态条件 组装 WHERE 和 参数,分离绑定
稳定性保障 任何 query 或 prepare 后必须判断成功
字符集设置 $mysqli->set_charset('utf8mb4') 避免乱码

四,相关函数

一,核心函数分类及用法

1. 连接与关闭
  • 创建连接

    php 复制代码
    // 面向对象
    $mysqli = new mysqli("localhost", "user", "password", "database", 3306);
    
    // 过程式
    $link = mysqli_connect("localhost", "user", "password", "database", 3306);
    • 失败行为 :默认返回 false,但若启用 MYSQLI_REPORT_STRICT 模式,会抛出 mysqli_sql_exception
  • 检查连接错误

    php 复制代码
    // 面向对象
    if ($mysqli->connect_errno) {
        die("连接失败: " . $mysqli->connect_error);
    }
    
    // 过程式
    if (mysqli_connect_errno()) {
        die("连接失败: " . mysqli_connect_error());
    }
  • 关闭连接

    php 复制代码
    $mysqli->close();       // 面向对象
    mysqli_close($link);    // 过程式

2. 执行查询
  • 执行普通查询

    php 复制代码
    // 面向对象
    $result = $mysqli->query("SELECT * FROM users");
    // 过程式
    $result = mysqli_query($link, "SELECT * FROM users");
    • 返回值
      • 成功(SELECT/SHOW/DESCRIBE)返回 mysqli_result 对象。
      • 成功(INSERT/UPDATE/DELETE)返回 true
      • 失败返回 false(或抛出异常)。
  • 获取结果数据

    php 复制代码
    // 获取关联数组
    while ($row = $result->fetch_assoc()) {
        echo $row["name"];
    }
    
    // 或直接获取所有数据
    $data = $result->fetch_all(MYSQLI_ASSOC);

3. 预处理语句(防 SQL 注入)
  • 步骤prepare()bind_param()execute()get_result()

    php 复制代码
    $stmt = $mysqli->prepare("INSERT INTO users (name, email) VALUES (?, ?)");
    $name = "Alice";
    $email = "alice@example.com";
    
    // 绑定参数(类型标识符:s=string, i=int, d=double, b=blob)
    $stmt->bind_param("ss", $name, $email);
    
    // 执行
    $stmt->execute();
    
    // 获取插入的 ID
    $inserted_id = $stmt->insert_id;
    
    // 关闭预处理语句
    $stmt->close();

4. 事务处理
  • 开启事务

    php 复制代码
    $mysqli->begin_transaction();
    
    try {
        $mysqli->query("UPDATE account SET balance = balance - 100 WHERE user_id = 1");
        $mysqli->query("UPDATE account SET balance = balance + 100 WHERE user_id = 2");
        $mysqli->commit(); // 提交事务
    } catch (mysqli_sql_exception $e) {
        $mysqli->rollback(); // 回滚
        echo "事务失败: " . $e->getMessage();
    }

5. 错误与异常处理
  • 启用严格异常模式

    php 复制代码
    $driver = new mysqli_driver();
    $driver->report_mode = MYSQLI_REPORT_STRICT | MYSQLI_REPORT_ERROR;
  • 捕获异常

    php 复制代码
    try {
        $mysqli->query("INVALID SQL");
    } catch (mysqli_sql_exception $e) {
        echo "错误信息: " . $e->getMessage();
        echo "错误代码: " . $e->getCode();
    }

二、PHP 8.0 关键变更与适配

1. 类型严格性
  • 参数类型检查

    例如 mysqli_query($link, 123) 中的第二个参数必须为字符串,否则抛出 TypeError

    php 复制代码
    // PHP 8.0 会报错,PHP 7.x 仅警告
    $mysqli->query(123); // 错误:参数必须为字符串
2. 弃用与移除
  • 弃用函数
    • mysqli::get_client_info()(无参数调用)需改为 mysqli_get_client_info()
  • 移除别名
    • mysqli_bind_param()mysqli_bind_result() 已移除,仅保留 mysqli_stmt_bind_param()

三、常用函数速查表

函数 用途 示例
mysqli_connect() 建立数据库连接 $link = mysqli_connect(...)
mysqli_query() 执行 SQL 查询 $result = mysqli_query($link, $sql)
mysqli_prepare() 创建预处理语句 $stmt = mysqli_prepare($link, $sql)
mysqli_stmt_bind_param() 绑定预处理语句参数 mysqli_stmt_bind_param($stmt, "si", ...)
mysqli_fetch_assoc() 获取关联数组结果 $row = mysqli_fetch_assoc($result)
mysqli_insert_id() 获取最后插入的 ID $id = mysqli_insert_id($link)
mysqli_affected_rows() 获取受影响的行数 $count = mysqli_affected_rows($link)
mysqli_real_escape_string() 转义字符串(用于非预处理语句) $safe = mysqli_real_escape_string($link, $input)

四、最佳实践

  1. 始终使用预处理语句:避免 SQL 注入,尤其是处理用户输入时。

  2. 启用异常模式

    php 复制代码
    $driver = new mysqli_driver();
    $driver->report_mode = MYSQLI_REPORT_STRICT | MYSQLI_REPORT_ERROR;
  3. 关闭调试信息:生产环境中隐藏数据库错误细节,记录到日志文件。

  4. 资源释放 :及时关闭 mysqli_result 和预处理语句对象。


项目名称:学生信息管理系统

功能需求

  1. 查看学生列表
  2. 添加新学生
  3. 编辑学生信息
  4. 删除学生
  5. 简单的搜索功能

技术栈

  • 前端:HTML + Bootstrap 5(极简界面)
  • 后端:PHP 8.0+(面向过程编程)
  • 数据库:MySQL 5.7+
  • 安全:MySQLi 预处理语句、输入过滤

项目结构

bash 复制代码
/student_manager
├── index.php         # 显示学生列表
├── create.php        # 添加新学生
├── edit.php          # 编辑学生信息
├── delete.php        # 删除学生
├── config.php        # 数据库配置
└── style.css         # 简单样式

数据库设计

表名:students

sql 复制代码
CREATE TABLE students (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50) NOT NULL,
    email VARCHAR(100) UNIQUE NOT NULL,
    age INT NOT NULL
);

核心代码实现

1. 数据库配置文件 (config.php)
php 复制代码
<?php
// 数据库配置
$host = 'localhost';
$user = 'root';
$password = '123456';
$database = 'student_db';

// 创建连接
$mysqli = new mysqli($host, $user, $password, $database);

// 检查连接
if ($mysqli->connect_error) {
    die("连接失败: " . $mysqli->connect_error);
}

// 设置字符集
$mysqli->set_charset('utf8mb4');
?>

2. 显示学生列表 (index.php)
php+HTML 复制代码
<?php
include 'config.php';

// 搜索功能
$search = $_GET['search'] ?? '';
$query = "SELECT * FROM students";
if (!empty($search)) {
    $query .= " WHERE name LIKE ?";
    $stmt = $mysqli->prepare($query);
    $search_term = "%$search%";
    $stmt->bind_param('s', $search_term);
} else {
    $stmt = $mysqli->prepare($query);
}

$stmt->execute();
$result = $stmt->get_result();
?>

<!DOCTYPE html>
<html>
<head>
    <title>学生管理系统</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container mt-5">
    <h2>学生列表</h2>
    
    <!-- 搜索框 -->
    <form class="mb-3">
        <input type="text" name="search" placeholder="输入姓名搜索" class="form-control">
        <button type="submit" class="btn btn-primary mt-2">搜索</button>
    </form>

    <!-- 添加学生链接 -->
    <a href="create.php" class="btn btn-success mb-3">添加新学生</a>

    <!-- 学生表格 -->
    <table class="table table-striped">
        <thead>
            <tr>
                <th>ID</th>
                <th>姓名</th>
                <th>邮箱</th>
                <th>年龄</th>
                <th>操作</th>
            </tr>
        </thead>
        <tbody>
            <?php while ($row = $result->fetch_assoc()): ?>
            <tr>
                <td><?= htmlspecialchars($row['id']) ?></td>
                <td><?= htmlspecialchars($row['name']) ?></td>
                <td><?= htmlspecialchars($row['email']) ?></td>
                <td><?= htmlspecialchars($row['age']) ?></td>
                <td>
                    <a href="edit.php?id=<?= $row['id'] ?>" class="btn btn-warning btn-sm">编辑</a>
                    <a href="delete.php?id=<?= $row['id'] ?>" class="btn btn-danger btn-sm" onclick="return confirm('确认删除?')">删除</a>
                </td>
            </tr>
            <?php endwhile; ?>
        </tbody>
    </table>
</div>
</body>
</html>

3. 添加学生 (create.php)
php+HTML 复制代码
<?php
include 'config.php';

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $name = $_POST['name'];
    $email = $_POST['email'];
    $age = $_POST['age'];

    // 使用预处理语句防止SQL注入
    $stmt = $mysqli->prepare("INSERT INTO students (name, email, age) VALUES (?, ?, ?)");
    $stmt->bind_param('ssi', $name, $email, $age);
    
    if ($stmt->execute()) {
        header('Location: index.php'); // 添加成功跳转
        exit;
    } else {
        $error = "添加失败: " . $stmt->error;
    }
}
?>

<!DOCTYPE html>
<html>
<head>
    <title>添加学生</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container mt-5">
    <h2>添加新学生</h2>
    <?php if (!empty($error)): ?>
        <div class="alert alert-danger"><?= $error ?></div>
    <?php endif; ?>
    
    <form method="POST">
        <div class="mb-3">
            <label class="form-label">姓名</label>
            <input type="text" name="name" class="form-control" required>
        </div>
        <div class="mb-3">
            <label class="form-label">邮箱</label>
            <input type="email" name="email" class="form-control" required>
        </div>
        <div class="mb-3">
            <label class="form-label">年龄</label>
            <input type="number" name="age" class="form-control" required>
        </div>
        <button type="submit" class="btn btn-primary">提交</button>
    </form>
</div>
</body>
</html>

4. 编辑学生 (edit.php)
php+HTML 复制代码
<?php
include 'config.php';

// 获取当前学生信息
$id = $_GET['id'];
$stmt = $mysqli->prepare("SELECT * FROM students WHERE id = ?");
$stmt->bind_param('i', $id);
$stmt->execute();
$student = $stmt->get_result()->fetch_assoc();

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $name = $_POST['name'];
    $email = $_POST['email'];
    $age = $_POST['age'];

    $stmt = $mysqli->prepare("UPDATE students SET name=?, email=?, age=? WHERE id=?");
    $stmt->bind_param('ssii', $name, $email, $age, $id);
    
    if ($stmt->execute()) {
        header('Location: index.php'); // 更新成功跳转
        exit;
    } else {
        $error = "更新失败: " . $stmt->error;
    }
}
?>

<!DOCTYPE html>
<html>
<head>
    <title>编辑学生</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container mt-5">
    <h2>编辑学生信息</h2>
    <?php if (!empty($error)): ?>
        <div class="alert alert-danger"><?= $error ?></div>
    <?php endif; ?>
    
    <form method="POST">
        <div class="mb-3">
            <label class="form-label">姓名</label>
            <input type="text" name="name" class="form-control" value="<?= htmlspecialchars($student['name']) ?>" required>
        </div>
        <div class="mb-3">
            <label class="form-label">邮箱</label>
            <input type="email" name="email" class="form-control" value="<?= htmlspecialchars($student['email']) ?>" required>
        </div>
        <div class="mb-3">
            <label class="form-label">年龄</label>
            <input type="number" name="age" class="form-control" value="<?= htmlspecialchars($student['age']) ?>" required>
        </div>
        <button type="submit" class="btn btn-primary">更新</button>
    </form>
</div>
</body>
</html>

5. 删除学生 (delete.php)
php 复制代码
<?php
include 'config.php';

if (isset($_GET['id'])) {
    $id = $_GET['id'];
    $stmt = $mysqli->prepare("DELETE FROM students WHERE id = ?");
    $stmt->bind_param('i', $id);
    
    if ($stmt->execute()) {
        header('Location: index.php'); // 删除成功跳转
    } else {
        die("删除失败: " . $stmt->error);
    }
}
?>

安全措施

  1. SQL注入防护
    • 所有用户输入通过 prepare + bind_param 处理。
  2. XSS防护
    • 使用 htmlspecialchars() 转义所有动态输出。
  3. 数据验证
    • 前端使用 required 属性确保必填字段。
    • 后端检查 $_SERVER['REQUEST_METHOD'] 防止直接访问。

相关推荐
用户962377954482 小时前
CTF 伪协议
php
随风飘的云6 小时前
mysql的innodb引擎对可重复读做了那些优化,可以避免幻读
mysql
用户962377954481 天前
DVWA 靶场实验报告 (High Level)
安全
数据智能老司机1 天前
用于进攻性网络安全的智能体 AI——在 n8n 中构建你的第一个 AI 工作流
人工智能·安全·agent
数据智能老司机1 天前
用于进攻性网络安全的智能体 AI——智能体 AI 入门
人工智能·安全·agent
用户962377954481 天前
DVWA 靶场实验报告 (Medium Level)
安全
red1giant_star1 天前
S2-067 漏洞复现:Struts2 S2-067 文件上传路径穿越漏洞
安全
用户962377954481 天前
DVWA Weak Session IDs High 的 Cookie dvwaSession 为什么刷新不出来?
安全
BingoGo2 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php
JaguarJack2 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php·服务端