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:数据库服务器地址,通常为本地主机。
  • usernamepassword:数据库的登录凭证。
  • database_name:要连接的具体数据库名称。

错误处理技巧:通过 connect_errnoconnect_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();

关键步骤解析

  1. prepare():创建预处理语句模板,? 表示参数占位符。
  2. bind_param():绑定变量到占位符,参数类型 is 表示第一个参数是整数(integer),第二个是字符串(string)。
  3. 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 的高级功能,用于保证多个数据库操作的“全有或全无”特性。它通过 BEGINCOMMITROLLBACK 三个关键字实现。

银行转账的比喻:假设从账户 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 的功能将持续扩展。建议开发者定期查阅官方文档,结合实际项目实践,逐步成长为数据库交互领域的专家。

最新发布