第十三章-PHP MySQL扩展
第十三章-PHP与MySQL
一,连接数据库
1. 使用 MySQLi(面向对象方式)
<?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
$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
$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;
?>
关键注意事项
-
防止 SQL 注入
-
使用预处理语句(如
$stmt->prepare()
+bindParam
或execute([参数])
)。 -
示例(PDO 预处理):
$stmt = $conn->prepare("INSERT INTO users (name, email) VALUES (:name, :email)"); $stmt->bindParam(':name', $name); $stmt->bindParam(':email', $email); $stmt->execute();
-
-
错误处理
- MySQLi 使用
$conn->connect_error
或mysqli_connect_error()
。 - PDO 使用异常捕获(
try...catch
+setAttribute
)。
- MySQLi 使用
-
关闭连接
- MySQLi:
$conn->close()
或mysqli_close($conn)
。 - PDO:
$conn = null
。
- MySQLi:
常见问题
-
连接失败可能原因
- 用户名/密码错误
- 数据库未启动
- 防火墙阻止连接
- PHP 未启用 MySQLi/PDO 扩展(检查
php.ini
)
-
启用扩展
在php.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 预处理插入
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 查询并遍历结果
$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 查询并遍历结果
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 预处理更新
$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 预处理更新
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 预处理删除
$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 预处理删除
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.安全与最佳实践
-
始终使用预处理语句
- 避免 SQL 注入攻击,禁止直接拼接用户输入到 SQL 中。
-
错误处理
- MySQLi 检查
$conn->error
,PDO 使用try...catch
捕获异常。
- MySQLi 检查
-
关闭连接
// MySQLi $conn->close();// PDO $conn = null;
-
验证输入数据
- 使用
filter_var()
验证邮箱、URL 等格式。 - 检查数值范围(如
$id > 0
)。
- 使用
6.完整流程图
1. 连接数据库 → 2. 准备SQL语句 → 3. 绑定参数 → 4. 执行操作 → 5. 处理结果 → 6. 关闭连接
7.扩展建议
-
使用 ORM 框架
如 Laravel 的 Eloquent 或 Doctrine,简化数据库操作。 -
事务处理
对于多个关联操作,使用事务保证数据一致性:// 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 的核心概念
- 类(Class)
- 类是对象的蓝图或模板,定义了对象的属性(数据)**和**方法(操作)。
- 比如:“狗”可以是一个类,它有颜色、品种这些属性,还有叫、跑这些方法。
- 对象(Object)
- 对象是类的实例,是具体存在的个体。
- 比如:“小黑”是一只狗,它是“狗”类的一个对象。
- 封装(Encapsulation)
- 把数据和操作数据的方法打包在一起,对外隐藏内部细节,只暴露必要的接口。
- 好处是保护数据安全,减少外部干扰。
- 继承(Inheritance)
- 子类可以继承父类的属性和方法,复用代码,还可以扩展或修改已有功能。
- 比如,“哈士奇”类可以继承“狗”类的基本特性,再加上自己的特性。
- 多态(Polymorphism)
- 同一种方法在不同对象上可以有不同表现。
- 比如,不同动物的“叫”方法,狗叫“汪汪”,猫叫“喵喵”,但都可以统一调用“叫”这个动作。
$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()
拼到数组里 - 查询限制条件齐全:
WHERE
、ORDER BY
、LIMIT
都要标准化
二、参数化查询(防SQL注入)
生产环境绝对禁止拼接变量,必须用预处理。
示例:按用户名模糊搜索
$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复制编辑$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()
只取一行,后面不用循环- 查不到数据时要有异常/提示处理
四、分页查询(带总数)
分页查询是非常常见需求,要返回数据和总数。
$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 + 参数绑定。
$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. 连接与关闭
-
创建连接:
// 面向对象 $mysqli = new mysqli("localhost", "user", "password", "database", 3306);// 过程式 $link = mysqli_connect("localhost", "user", "password", "database", 3306);
- 失败行为:默认返回
false
,但若启用MYSQLI_REPORT_STRICT
模式,会抛出mysqli_sql_exception
。
- 失败行为:默认返回
-
检查连接错误:
// 面向对象 if ($mysqli->connect_errno) {die("连接失败: " . $mysqli->connect_error); }// 过程式 if (mysqli_connect_errno()) {die("连接失败: " . mysqli_connect_error()); }
-
关闭连接:
$mysqli->close(); // 面向对象 mysqli_close($link); // 过程式
2. 执行查询
-
执行普通查询:
// 面向对象 $result = $mysqli->query("SELECT * FROM users"); // 过程式 $result = mysqli_query($link, "SELECT * FROM users");
- 返回值:
- 成功(SELECT/SHOW/DESCRIBE)返回
mysqli_result
对象。 - 成功(INSERT/UPDATE/DELETE)返回
true
。 - 失败返回
false
(或抛出异常)。
- 成功(SELECT/SHOW/DESCRIBE)返回
- 返回值:
-
获取结果数据:
// 获取关联数组 while ($row = $result->fetch_assoc()) {echo $row["name"]; }// 或直接获取所有数据 $data = $result->fetch_all(MYSQLI_ASSOC);
3. 预处理语句(防 SQL 注入)
-
步骤:
prepare()
→bind_param()
→execute()
→get_result()
。$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. 事务处理
-
开启事务:
$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. 错误与异常处理
-
启用严格异常模式:
$driver = new mysqli_driver(); $driver->report_mode = MYSQLI_REPORT_STRICT | MYSQLI_REPORT_ERROR;
-
捕获异常:
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 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) |
四、最佳实践
-
始终使用预处理语句:避免 SQL 注入,尤其是处理用户输入时。
-
启用异常模式:
$driver = new mysqli_driver(); $driver->report_mode = MYSQLI_REPORT_STRICT | MYSQLI_REPORT_ERROR;
-
关闭调试信息:生产环境中隐藏数据库错误细节,记录到日志文件。
-
资源释放:及时关闭
mysqli_result
和预处理语句对象。
项目名称:学生信息管理系统
功能需求
- 查看学生列表
- 添加新学生
- 编辑学生信息
- 删除学生
- 简单的搜索功能
技术栈
- 前端:HTML + Bootstrap 5(极简界面)
- 后端:PHP 8.0+(面向过程编程)
- 数据库:MySQL 5.7+
- 安全:MySQLi 预处理语句、输入过滤
项目结构
/student_manager
├── index.php # 显示学生列表
├── create.php # 添加新学生
├── edit.php # 编辑学生信息
├── delete.php # 删除学生
├── config.php # 数据库配置
└── style.css # 简单样式
数据库设计
表名:students
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
// 数据库配置
$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
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
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
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
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);}
}
?>
安全措施
- SQL注入防护
- 所有用户输入通过
prepare
+bind_param
处理。
- 所有用户输入通过
- XSS防护
- 使用
htmlspecialchars()
转义所有动态输出。
- 使用
- 数据验证
- 前端使用
required
属性确保必填字段。 - 后端检查
$_SERVER['REQUEST_METHOD']
防止直接访问。
- 前端使用
相关文章:
第十三章-PHP MySQL扩展
第十三章-PHP与MySQL 一,连接数据库 1. 使用 MySQLi(面向对象方式) <?php // 数据库参数 $host localhost; $username root; $password ; $database test_db;// 创建连接 $conn new mysqli($host, $username, $password, $databa…...
在服务器中,搭建FusionCompute,实现集群管理
序:需要自备一台服务器,并安装部署好KVM,自行下载镜像,将所需的CNA和VRM镜像放到服务器中,小编所用的进项版本如下,读者可自行根据需求下载其它版本的镜像。 CNA镜像:FusionCompute_CNA-8.3.0-…...
嵌入式开发学习日志Day11
一、函数的递归调用 在调用一个函数的过程中,又出现直接或者间接的调用函数本身,称之为函数的递归调用; 函数的递归调用是使用大量的内存空间完成程序进行的; 1.间接调用 2.直接调用 注意: 上图仅为示意,…...
【线性规划】对偶问题的实际意义与重要性质 学习笔记
【线性规划】对偶问题的实际意义与重要性质_哔哩哔哩_bilibili...
代码随想录第30天:动态规划3
一、01背包理论基础(Kama coder 46) “01背包”:有n件物品和一个最多能背重量为w 的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。每件物品只能用一次,求解将哪些物品装入背包里物品价值总和最大。 1. 确…...
DSP48E2 的 MAC模式功能仿真
DSP48E2 仿真代码: 测试的功能为 P i ( A D ) ∗ B P i − 1 P_{i} (AD) * B P_{i-1} Pi(AD)∗BPi−1 timescale 1ns / 1nsmodule dsp_tb;// 输入reg CLK;reg CE;reg SCLR;reg signed [26:0] A, D;reg signed [17:0] B;// 输出wire signed [47:0] P;par…...
【环境配置】Mac电脑安装运行R语言教程 2025年
一、安装 Xcode Command Line Tools 打开终端,输入如下命令: xcode-select --install安装完成后,输入如下命令,能看见版本号说明安装成功 gcc --version二、下载安装R语言 https://mirrors.tuna.tsinghua.edu.cn/CRAN/ 点开后…...
常见算法的总结与实现思路
前言 hello,我是Maybe。昨天和今天花了两天左右的时间。把常见的排序算法都学完了,自己也实现了一遍。感觉收获满满,但是过程是艰辛的。下面我将分享代码和思维导图,希望可以帮助到大家。 思维导图(含注意事项,实现思…...
Ethan独立开发产品日报 | 2025-04-27
1. CreateWise AI 旨在提升你工作效率的AI播客编辑器 人工智能播客编辑器,让你的播客制作速度提升10倍!它可以自动去除口头语和沉默,生成节目笔记和精彩片段,还能一键制作适合社交媒体分享的短视频——所有这些功能都只需一次点…...
5G与边缘计算:协同发展,开启智慧世界新篇章
**5G与边缘计算:协同发展,开启智慧世界新篇章 ** 大家好,我是Echo_Wish。今天我们来探讨一个备受关注的技术话题——5G与边缘计算的协同发展。随着5G网络的逐步普及以及边缘计算技术的快速发展,二者的结合为我们带来了前所未有的创…...
AcWing 885:求组合数 I ← 杨辉三角
【题目来源】 https://www.acwing.com/problem/content/887/ 【题目描述】 给定 n 组询问,每组询问给定两个整数 a,b,请你输出 C(a,b) mod (10^97) 的值。 【输入格式】 第一行包含整数 n。 接下来 n 行,每行包含一组 a 和 b。 …...
Python3:Jupyterlab 安装和配置
Python3:Jupyterlab 安装和配置 Jupyter源于Ipython Notebook项目,是使用Python(也有R、Julia、Node等其他语言的内核)进行代码演示、数据分析、机器学习、可视化、教学的非常好的工具。 最新的基于web的交互式开发环境,适用于n…...
如何搭建spark yarn模式的集合集群
一、环境准备 在搭建 Spark on YARN 集群之前,需要确保以下环境已经准备就绪: 操作系统:推荐使用 CentOS、Ubuntu 等 Linux 发行版。 Java 环境:确保安装了 JDK 1.8 或更高版本。 Hadoop 集群:已经搭建并运行的 Had…...
智能座舱架构中芯片算力评估
在智能座舱(Intelligent Cockpit)领域,芯片的算力是决定系统性能、响应速度以及用户体验的关键因素之一。 随着汽车智能化程度的不断提高,智能座舱对芯片的算力、功耗、集成度以及安全性提出了更高的要求。 智能座舱架构中芯片算…...
STM32完整内存地址空间分配详解
在STM32这类基于ARM Cortex-M的32位微控制器中,整个4GB的地址空间(从0x00000000到0xFFFFFFFF)有着非常系统化的分配方案,每个区域都有其特定的用途。下面我将详细介绍这些地址区域的分配及其功能: STM32完整内存地址空间分配详解(0x00000000…...
叉车司机N1考试的实操部分有哪些注意事项?
叉车司机 N1 考试实操部分分为场地考试和场内道路考试,以下是一些注意事项: 场地考试 起步:检查车辆仪表和个人仪容,穿好工作服、戴安全帽,不穿拖鞋等不符规定的鞋。同时检查换挡和换向操纵杆在空档位置,…...
【行业特化篇2】金融行业简历特化指南:合规性要求与风险控制能力的艺术化呈现
写在最前 作为一个中古程序猿,我有很多自己想做的事情,比如埋头苦干手搓一个低代码数据库设计平台(目前只针对写java的朋友),比如很喜欢帮身边的朋友看看简历,讲讲面试技巧,毕竟工作这么多年,也做到过高管,有很多面人经历,意见还算有用,大家基本都能拿到想要的offe…...
Linux 定时备份到windows 方案比较
1 传输协议比较 特性SCPRSYNCSFTP基本功能文件传输(本地与远程)文件和目录的同步与传输文件管理(上传、下载、删除等)增量传输不支持增量传输支持增量传输不支持增量传输性能传输速度较慢,效率低高效,适合…...
【网络编程】TCP/IP四层模型、MAC和IP
1. TCP/IP的四层模型 网络模型的目的:规范通信标准,确保不同设备和系统之间能够有效通信 对比OSI模型与TCP/IP模型: OSI模型的七层架构(物理层、数据链路层、网络层、传输层、会话层、表示层、应用层)TCP/IP模型的四…...
Java学习手册: IoC 容器与依赖注入
一、IoC 容器概述 IoC(Inversion of Control,控制反转)容器是 Spring 框架的核心组件之一。它负责创建对象、管理对象的生命周期以及对象之间的依赖关系。通过将对象的创建和管理交给 IoC 容器,开发者可以实现代码的松耦合&#…...
Web 基础与Nginx访问统计
目录 Web基础 域名与DNS 域名的结构 网页与HTML 网页概述 HTML 概述 HTML基本标签 1、HTML 语法规则 2、HTML 文件结构 静态网页和动态网页 HTTP协议概述 HTTP方法 HTTP状态码 Nginx访问状态统计 Web基础 域名与DNS 网络是基于 TCP/IP 协议进行通信和连接的,每一台主机都有一…...
了解Android studio 初学者零基础推荐(1)
线上学习课程链接 开发Andorid App 使用的语言有很多,包括java, kotlin,C,等,首先让我们了解kotlin这个热门语言。 kotlin 程序 fun main() {println("hello,xu") } kotlin中的函数定义语法:函数名称在fun关键字后面࿰…...
Android Studio 2024版,前进返回按钮丢失解决
最近升级完AS最新系统后,顶部的前进和返回按钮默认隐藏了 解决方案: 1. 打开settings 2. 找到左侧 Appearance & Behavior 下面点击 Menus and Toolbars 3. 点击 Main Toolar 4. 点击Left,右键选择 Add Actions 5. 弹框中选择 Main Me…...
详解UnityWebRequest类
什么是UnityWebRequest类 UnityWebRequest 是 Unity 引擎中用于处理网络请求的一个强大类,它可以让你在 Unity 项目里方便地与网络资源进行交互,像发送 HTTP 请求、下载文件等操作都能实现。下面会详细介绍 UnityWebRequest 的相关内容。 UnityWebRequ…...
安装qt4.8.7
QT4.8.7安装详细教程(MinGW 4.8.2和QTCreator4.2.0)_qtcreater482-CSDN博客 QT4.8.7安装详细教程(MinGW 4.8.2和QTCreator4.2.0) 1、下载 1)下载QT4.8.7 http://download.qt.io/archive/ 名称:qt-opensource-windows-x86-mingw482…...
2025系统架构师---管道/过滤器架构风格
引言 在分布式系统与数据密集型应用主导技术演进的今天,管道/过滤器架构风格(Pipes and Filters Architecture Style)凭借其数据流驱动、组件解耦与并行处理能力,成为处理复杂数据转换任务的核心范式。从Unix命令…...
仙宫云ComfyUI —【Wan2.1】AI视频生成部署
【Wan2.1】AI视频生成本地部署与使用技巧全面详解_哔哩哔哩_bilibili 所有模型下载:https://pan.quark.cn/s/9d793aa1b258 Runninghub本期课程工作流下载(可获得1000RH币):https://www.runninghub.cn/?utm_sourcekol01-RH145 仙…...
学成在线。。。
一:讲师管理 介绍:可以实现对讲师的分页展示,多条件组合分页查询,对讲师的添加,修改,删除操作。 针对于添加来说,使用requestBody注解,搭配postmapping接收数据,使用service层的对象,调用mapper方法,向数据库中保存数据。 修改: 先根据讲师id,查询出讲师,再去…...
Python爬虫实战:获取猫yan电影网最新热门电影数据并做分析,为51观影做参考
一、引言 随着互联网的迅速发展,电影信息获取更加便捷。猫yan电影作为国内知名电影信息平台,提供了丰富电影数据。对于我们而言,获取并分析这些数据,能为用户提供更有价值的观影建议。本文详细介绍使用 Python 的 Scrapy 框架实现猫yan电影数据爬取与分析,为 “五一” 观…...
将有序数组转换为高度平衡二叉搜索树 | 详解与Java实现
文章目录 1. 问题描述2. 方法思路核心思想:分治法 + 递归3. 代码实现Java实现(含注释)4. 复杂度分析5. 关键点解释为何选择中间节点?为何使用 `left + (right - left) / 2` 而非 `(left + right) / 2`?6. 扩展优化迭代法实现(非递归)优化空间7. 总结1. 问题描述 108.将…...
普推知产:商标驳回复审下初步审定公告了!
近日客户的商标驳回复审后终于下初审公告了,经过一年多时间,当时申请时知道这个商标名称会被驳回,因为有相同一模一样的,客户就想要这个名称,因为与创始人的姓名是相关的,普推知产商标老杨经分析后…...
网工笔记-网络层
概述: 两种观点: 1.面向连接的可靠传输 2.面向无连接的,尽最大努力完成交付数据报服务 虚电路服务(可靠传输) 数据报服务(尽力而为) 两者的对比: 不管是虚电路还是数据报服务都是…...
el-Input输入数字自动转千分位进行展示
el-Input输入数字自动转千分位进行展示,存储值不变 子组件: <template><el-input ref"inputRef" :disabled"disabled" clearable v-model"displayValue" v-bind"$attrs" input"handleInput&quo…...
基于 Spring Boot 瑞吉外卖系统开发(九)
基于 Spring Boot 瑞吉外卖系统开发(九) 保存菜品 菜品管理页面提供了一个“新增菜品”按钮,单击该按钮时,会打开新增菜品页面。 请求路径/dish,请求方法POST,参数使用DishDto类接收。 DishDto 添加f…...
C++复习补充 类型转换和RTTI
类型转换和RTTI 类型转换类与类之间的类型转换四种显示类型转换类型转换注意事项RTTI 类型转换 在 C 中,operator int() 是用户定义的类型转换运算符(User-Defined Conversion Operator),允许自定义对象隐式或显式转换为特定类型…...
QT采用mqtt进行通信(17.1)
文章目录 1.试错历程2. qt5.8安装3. 开始搞了4. 测试连接mqtt broker1.试错历程 尝试过网上说的各种版本,官方库和第三方库,试过qt5.9.9, qt5.12, qt5.12.2, qt5.14 等各个版本,都能编译通过,调用mqtt库,但是都不能连接成功,真的是试吐了,不知道他们的为什么都能成功,…...
基于 BERT 微调一个意图识别(Intent Classification)模型
基于 BERT 微调一个意图识别(Intent Classification)模型,你的意图类别包括: 查询天气获取新闻咨询想听音乐想添加备忘查询备忘获取家政服务结束对话增加音量减小音量其他 具体实现步骤(详细版) 1. 准备你…...
人工智能大语言模型与AI芯片新进展:技术演进与商业化路径
人工智能大语言模型与AI芯片新进展:技术演进与商业化路径 Latest Advances in AI Large Language Models and Chips: Technological Evolution and Commercialization Pathways 一、研究背景与意义(Research Background and Significance) 技…...
【Linux】Java 开发者的 Linux 常用命令指南
Java 开发者的 Linux 常用命令指南 目录标题 Java 开发者的 Linux 常用命令指南1. Linux 目录结构2. 系统信息命令3. 服务管理系统服务防火墙管理 4. 文本编辑 (vi/vim)常用模式 5. 文件和目录操作查看与导航创建与删除查看文件内容查找文件 6. 用户管理7. 压缩和解压8. 权限管…...
全开源、私有化部署!轻量级用户行为分析系统-ClkLog
ClkLog是一款支持私有化部署的全开源埋点数据采集与分析系统,兼容Web、App、小程序多端埋点,快速洞察用户访问路径、行为轨迹,并生成多维用户画像。助力中小团队搭建轻量灵活的用户行为分析平台。 为什么需要一款私有化的埋点分析系统&#x…...
【Mybatis】Mybatis基础
文章目录 前言一、搭建MyBatis1.1 创建maven工程1.2 加入log4j日志功能1.3 MyBatis的增删改查1.4 核心配置文件详解 二、MyBatis获取参数值的两种方式2.1 单个字面量类型的参数2.2 多个字面量类型的参数2.3 map集合类型的参数2.4 实体类类型的参数2.5 使用Param标识参数 三、 M…...
(002)Excel 使用图表,统计
第一步新建数据,将数据转成表格: 选中表格数据,右下角小图标:汇总 图表。...
云服务器主动防御策略与自动化防护(下)
三、纵深防御体系构建 1. 系统层防护 # 自动安全更新配置 sudo apt install unattended-upgrades sudo dpkg-reconfigure unattended-upgrades# 内核防护加固 sudo vim /etc/sysctl.conf# 添加以下参数: net.ipv4.conf.all.rp_filter1 net.ipv4.conf.default.rp_f…...
在前端应用领域驱动设计(DDD):必要性、挑战与实践指南
引言 领域驱动设计(Domain-Driven Design,简称 DDD)起源于后端复杂业务系统建模领域,是 Eric Evans 在 2003 年提出的一套理论体系。近年来,随着前端工程化与业务复杂度的持续提升,"前端也要 DDD&quo…...
【软件工程】需求分析详解
需求分析是确保软件产品符合用户期望、降低返工风险的关键环节。通过系统化的方法,团队可以从多渠道获取需求,利用多种建模技术对需求进行结构化分析,并编写规范的需求规格说明书(SRS),最终通过评审、验证及…...
FPGA-DDS信号发生器
FPGA-DDS信号发生器 DDS基本原理 FPGA实现的DDS(直接数字频率合成)波形生成器是一种高效、灵活的数字信号生成技术,广泛应用于通信、雷达和测试设备中。其核心原理是通过数字计算生成特定频率的波形。 DDS通过相位累加、查找表(LUT)…...
二进制、高位低位、位移操作与进制转换全解
二进制、高位低位、位移操作与进制转换全解 在计算机科学中,理解高位与低位、左移与右移、进制转换与位运算非常重要。这篇文章用清晰直观的方式梳理这些基本概念。 高位与低位 低位:二进制中靠右的位,权值较小(例如 (2^0, 2^1…...
docker存储
注意:数据卷挂载(卷映射):Docker会自动创建数据卷,并将容器运行所需的文件复制到数据卷中。 目录挂载:如果宿主机上没有对应的目录,容器会因为缺少运行所需的文件而出错。 1.目录挂载 指令&am…...
回归预测 | Matlab实现DBO-LightGBM蜣螂算法优化轻量级梯度提升机多输入单输出回归预测,作者:机器学习之心
回归预测 | Matlab实现DBO-LightGBM蜣螂算法优化轻量级梯度提升机多输入单输出回归预测,作者:机器学习之心 目录 回归预测 | Matlab实现DBO-LightGBM蜣螂算法优化轻量级梯度提升机多输入单输出回归预测,作者:机器学习之心预测效果…...
[ 问题解决 ] sqlite3.ProgrammingError: SQLite objects created in a thread can ...
目录 为什么会出现这个问题? 解决方法一:每个请求新建自己的连接(推荐) 解决方法二:允许 SQLite 跨线程使用连接(不推荐) 小结 当你在 python 中使用 Flask 里面调用了数据库的操作的时候&a…...