PHP 5 MySQLi 函数(长文解析)
💡一则或许对你有用的小广告
欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于
Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...
,点击查看项目介绍 ;- 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;
截止目前, 星球 内专栏累计输出 82w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2900+ 小伙伴加入学习 ,欢迎点击围观
前言:为什么选择 PHP 5 MySQLi 函数?
在 PHP 开发中,数据库操作是构建动态 Web 应用的核心环节。随着 PHP 版本的迭代,MySQLi(MySQL Improved)函数作为 MySQL 扩展的升级版本,逐渐取代了过时的 mysql_*
函数。它不仅提供了面向过程和面向对象的双重编程模式,还增强了安全性、性能和功能的灵活性。对于编程初学者和中级开发者而言,掌握 PHP 5 MySQLi 函数是构建可靠数据库交互能力的关键一步。
MySQLi 的核心优势可以用“快递升级版”来比喻:就像从普通快递升级为带追踪功能的智能物流系统,它不仅能更快地完成数据传输,还能实时监控错误、优化路径,并提供更安全的交付保障。本文将从基础到实践,逐步讲解如何利用 MySQLi 函数高效操作数据库,同时通过代码示例和实际案例加深理解。
一、连接数据库:建立与 MySQL 的通信桥梁
1.1 基础连接方法
要操作数据库,首先需要建立与 MySQL 服务器的连接。MySQLi 提供了两种连接模式:面向过程和面向对象。以下是一个典型的连接示例:
// 面向过程写法
$connection = mysqli_connect("localhost", "username", "password", "database_name");
if (mysqli_connect_errno()) {
die("连接失败: " . mysqli_connect_error());
}
// 面向对象写法
$mysqli = new mysqli("localhost", "username", "password", "database_name");
if ($mysqli->connect_errno) {
die("连接失败: " . $mysqli->connect_error);
}
关键参数解析:
localhost
:数据库服务器地址,通常为本地主机。username
和password
:数据库的登录凭证。database_name
:要连接的具体数据库名称。
错误处理技巧:通过 connect_errno
和 connect_error
可以快速定位连接失败的原因,例如网络问题或权限错误。
1.2 连接配置的优化
在实际开发中,建议将连接参数封装到单独的配置文件中,并通过条件判断实现动态选择环境(如开发环境与生产环境)。例如:
// config.php
return [
'host' => 'localhost',
'user' => 'dev_user',
'password' => 'dev_password',
'database' => 'dev_db'
];
// 使用时
$settings = require 'config.php';
$mysqli = new mysqli($settings['host'], $settings['user'], $settings['password'], $settings['database']);
这种设计模式既能提升代码的可维护性,也便于后续的扩展。
二、执行 SQL 查询:从简单查询到复杂操作
2.1 基本 SELECT 查询
SELECT 查询是数据库操作中最常见的场景。通过 mysqli_query()
函数或 query()
方法(面向对象)可以轻松执行查询:
// 面向过程写法
$result = mysqli_query($connection, "SELECT * FROM users WHERE status = 'active'");
while ($row = mysqli_fetch_assoc($result)) {
echo "用户名:" . $row['username'] . "<br>";
}
mysqli_free_result($result);
// 面向对象写法
$result = $mysqli->query("SELECT * FROM products ORDER BY price DESC");
foreach ($result as $row) {
echo "产品名称:" . $row['name'] . ",价格:" . $row['price'] . "<br>";
}
关键函数解析:
mysqli_fetch_assoc()
:逐行获取结果集,返回关联数组。mysqli_free_result()
:释放结果集内存,提高资源利用率。
2.2 INSERT 和 UPDATE 操作
对于数据写入操作,可以通过 mysqli_affected_rows()
函数确认执行结果:
// 插入新用户
$insertQuery = "INSERT INTO users (username, email) VALUES ('john_doe', 'john@example.com')";
if ($mysqli->query($insertQuery) === TRUE) {
echo "新记录插入成功。ID:" . $mysqli->insert_id;
} else {
echo "错误:" . $mysqli->error;
}
// 更新用户信息
$updateQuery = "UPDATE users SET email = 'new@example.com' WHERE id = 5";
$mysqli->query($updateQuery);
echo "受影响行数:" . $mysqli->affected_rows;
注意事项:
insert_id
可获取自增主键的最新值。- 始终检查
error
属性以捕获潜在错误。
三、预处理语句:防御 SQL 注入的核心武器
3.1 什么是预处理?
预处理语句(Prepared Statements)通过将 SQL 语句和数据分离,有效防止 SQL 注入攻击。它的工作原理类似于“模板+数据填充”模式,确保数据始终被视为参数而非可执行代码。
比喻解释:想象你正在填写一份表格,模板已经固定了格式,而输入的数据只能填在特定位置,无法改变表格的结构或逻辑。
3.2 实际应用示例
// 面向对象的预处理写法
$stmt = $mysqli->prepare("INSERT INTO comments (user_id, content) VALUES (?, ?)");
$stmt->bind_param("is", $user_id, $comment_text);
$user_id = 10;
$comment_text = "这是一个测试评论!";
$stmt->execute();
echo "插入成功,影响行数:" . $stmt->affected_rows;
// 关闭预处理语句
$stmt->close();
关键步骤解析:
prepare()
:创建预处理语句模板,?
表示参数占位符。bind_param()
:绑定变量到占位符,参数类型is
表示第一个参数是整数(integer),第二个是字符串(string)。execute()
:执行语句,数据自动转义并安全注入。
3.3 处理查询结果的预处理
对于 SELECT 查询,预处理同样适用,并可通过 bind_result()
获取结果:
$stmt = $mysqli->prepare("SELECT username, email FROM users WHERE id = ?");
$stmt->bind_param("i", $user_id);
$stmt->execute();
// 绑定结果变量
$stmt->bind_result($username, $email);
$stmt->fetch();
echo "用户名:" . $username . ",邮箱:" . $email;
$stmt->close();
优势对比:传统查询需要手动转义用户输入(如 mysqli_real_escape_string()
),而预处理通过参数化查询自动处理,安全性更高。
四、事务管理:确保数据操作的原子性
事务(Transaction)是 MySQLi 的高级功能,用于保证多个数据库操作的“全有或全无”特性。它通过 BEGIN
、COMMIT
和 ROLLBACK
三个关键字实现。
银行转账的比喻:假设从账户 A 向账户 B 转账 100 元,事务确保:如果 A 的余额不足,整个操作会回滚,避免 A 账户透支而 B 账户收到款项。
4.1 事务操作示例
// 开启事务
$mysqli->begin_transaction();
try {
// 扣减用户 A 的余额
$mysqli->query("UPDATE accounts SET balance = balance - 100 WHERE user_id = 1");
// 增加用户 B 的余额
$mysqli->query("UPDATE accounts SET balance = balance + 100 WHERE user_id = 2");
// 提交事务
$mysqli->commit();
echo "转账成功!";
} catch (Exception $e) {
// 回滚操作
$mysqli->rollback();
echo "转账失败,已回滚:" . $e->getMessage();
}
关键点:
- 在事务期间,所有数据修改操作都处于“待提交”状态。
- 若发生错误,
rollback()
将撤销所有未提交的更改。 - 需确保数据库引擎支持事务(如 InnoDB)。
五、错误处理与调试技巧
5.1 错误模式的配置
MySQLi 提供了多种错误报告模式,建议在开发阶段启用详细错误提示:
// 启用错误报告
$mysqli->report_mode = MYSQLI_REPORT_ALL;
$mysqli->report_constant = E_ALL;
5.2 自定义错误处理函数
通过 mysqli_set_exception_mode()
可以将错误抛出为异常,便于集中处理:
// 面向对象模式启用异常
$mysqli->set_exception_mode(true);
try {
$mysqli->query("SELECT * FROM non_existent_table");
} catch (mysqli_sql_exception $e) {
echo "数据库错误:" . $e->getMessage();
}
六、性能优化与最佳实践
6.1 减少数据库往返次数
尽量合并多个查询为一条,例如:
// 低效写法(多次查询)
for ($i = 1; $i <= 5; $i++) {
$mysqli->query("INSERT INTO logs VALUES ($i, '操作')");
}
// 高效写法(单次批量插入)
$mysqli->query("INSERT INTO logs (id, action) VALUES (1, '操作'), (2, '操作'), ...");
6.2 使用连接池和持久化连接
在高并发场景下,通过 mysqli_pconnect()
建立持久化连接可减少重复握手开销:
$connection = mysqli_pconnect("localhost", "user", "pass", "db");
结论:掌握 MySQLi 函数,构建健壮的 PHP 应用
PHP 5 MySQLi 函数不仅是连接 PHP 与 MySQL 的桥梁,更是开发者构建高效、安全 Web 应用的基石。通过本文的讲解,读者可以:
- 理解 MySQLi 的核心功能与优势;
- 掌握从基础连接到高级事务的完整操作流程;
- 学会通过预处理语句防御 SQL 注入;
- 运用错误处理和性能优化技巧提升代码质量。
未来,随着 PHP 版本的更新(如 PHP 8+),MySQLi 的功能将持续扩展。建议开发者定期查阅官方文档,结合实际项目实践,逐步成长为数据库交互领域的专家。