PHP MySQLi扩展
PHP MySQLi扩展[编辑 | 编辑源代码]
PHP MySQLi扩展(MySQL Improved Extension)是PHP用于与MySQL数据库交互的增强接口,提供面向对象和面向过程两种编程方式。相比旧的mysql_*函数,MySQLi支持预处理语句、事务处理、多语句查询等现代数据库操作特性,是PHP开发者连接MySQL数据库的推荐方式之一。
概述[编辑 | 编辑源代码]
MySQLi扩展在PHP 5.0版本引入,主要改进包括:
- 支持面向对象和面向过程两种API风格
- 预处理语句(防止SQL注入)
- 事务控制(ACID兼容)
- 多查询执行
- 服务器状态检查
- 增强的调试能力
安装与配置[编辑 | 编辑源代码]
MySQLi通常随PHP默认安装,可通过以下命令检查是否启用:
<?php
phpinfo(); // 查找mysqli模块
?>
若未安装,需在php.ini中取消注释:
extension=mysqli
基础用法[编辑 | 编辑源代码]
连接数据库[编辑 | 编辑源代码]
面向对象风格:
<?php
$mysqli = new mysqli("localhost", "username", "password", "database");
// 检查连接
if ($mysqli->connect_error) {
die("连接失败: " . $mysqli->connect_error);
}
echo "连接成功";
?>
面向过程风格:
<?php
$conn = mysqli_connect("localhost", "username", "password", "database");
if (!$conn) {
die("连接失败: " . mysqli_connect_error());
}
echo "连接成功";
?>
执行查询[编辑 | 编辑源代码]
查询示例:
<?php
$sql = "SELECT id, name FROM users";
$result = $mysqli->query($sql);
if ($result->num_rows > 0) {
while($row = $result->fetch_assoc()) {
echo "ID: " . $row["id"]. " - Name: " . $row["name"]. "<br>";
}
} else {
echo "0 结果";
}
?>
预处理语句[编辑 | 编辑源代码]
预处理是防止SQL注入的最佳实践:
<?php
$stmt = $mysqli->prepare("INSERT INTO users (name, email) VALUES (?, ?)");
$stmt->bind_param("ss", $name, $email);
// 设置参数并执行
$name = "John";
$email = "john@example.com";
$stmt->execute();
echo "新记录插入成功";
$stmt->close();
?>
参数类型说明:
- i - 整数
- d - 双精度浮点数
- s - 字符串
- b - 二进制数据
事务处理[编辑 | 编辑源代码]
MySQLi支持数据库事务:
<?php
$mysqli->autocommit(FALSE);
try {
$mysqli->query("UPDATE accounts SET balance = balance - 100 WHERE user_id = 1");
$mysqli->query("UPDATE accounts SET balance = balance + 100 WHERE user_id = 2");
$mysqli->commit();
echo "转账成功";
} catch (Exception $e) {
$mysqli->rollback();
echo "事务失败: " . $e->getMessage();
}
?>
错误处理[编辑 | 编辑源代码]
推荐的错误处理方式:
<?php
// 面向对象
if ($mysqli->errno) {
echo "错误代码: " . $mysqli->errno . "<br>";
echo "错误信息: " . $mysqli->error;
}
// 面向过程
if (mysqli_errno($conn)) {
echo "错误代码: " . mysqli_errno($conn) . "<br>";
echo "错误信息: " . mysqli_error($conn);
}
?>
性能优化[编辑 | 编辑源代码]
多查询[编辑 | 编辑源代码]
MySQLi支持多查询执行(但需谨慎使用):
<?php
$sql = "
SELECT * FROM users;
SELECT * FROM products;
";
if ($mysqli->multi_query($sql)) {
do {
if ($result = $mysqli->store_result()) {
while ($row = $result->fetch_row()) {
print_r($row);
}
$result->free();
}
} while ($mysqli->more_results() && $mysqli->next_result());
}
?>
结果缓冲[编辑 | 编辑源代码]
使用缓冲查询提高性能:
<?php
// 默认缓冲查询
$result = $mysqli->query("SELECT * FROM large_table");
// 无缓冲查询(节省内存)
$result = $mysqli->query("SELECT * FROM very_large_table", MYSQLI_USE_RESULT);
?>
实际案例[编辑 | 编辑源代码]
用户注册系统[编辑 | 编辑源代码]
完整示例展示用户注册流程:
<?php
class UserRegistration {
private $mysqli;
public function __construct($mysqli) {
$this->mysqli = $mysqli;
}
public function register($username, $password, $email) {
// 检查用户名是否存在
$stmt = $this->mysqli->prepare("SELECT id FROM users WHERE username = ?");
$stmt->bind_param("s", $username);
$stmt->execute();
$stmt->store_result();
if ($stmt->num_rows > 0) {
throw new Exception("用户名已存在");
}
$stmt->close();
// 插入新用户
$hashedPassword = password_hash($password, PASSWORD_DEFAULT);
$stmt = $this->mysqli->prepare("INSERT INTO users (username, password, email) VALUES (?, ?, ?)");
$stmt->bind_param("sss", $username, $hashedPassword, $email);
if (!$stmt->execute()) {
throw new Exception("注册失败: " . $stmt->error);
}
return $stmt->insert_id;
}
}
// 使用示例
$db = new mysqli("localhost", "user", "pass", "app_db");
$registration = new UserRegistration($db);
try {
$userId = $registration->register("newuser", "secure123", "new@example.com");
echo "注册成功,用户ID: " . $userId;
} catch (Exception $e) {
echo "错误: " . $e->getMessage();
}
?>
与PDO的比较[编辑 | 编辑源代码]
特性 | MySQLi | PDO |
---|---|---|
数据库支持 | 仅MySQL | 多种数据库 |
预处理语句 | 支持 | 支持 |
命名参数 | 不支持 | 支持 |
对象映射 | 有限支持 | 完整ORM支持 |
错误处理 | 多种模式 | 异常为主 |
最佳实践[编辑 | 编辑源代码]
1. 始终使用预处理语句防止SQL注入 2. 合理使用事务保证数据一致性 3. 关闭自动提交(autocommit(FALSE)) 4. 及时释放查询结果(free()/close()) 5. 使用适当的错误处理机制 6. 生产环境关闭错误显示(display_errors=Off)
常见问题[编辑 | 编辑源代码]
Q: 何时选择MySQLi而非PDO?
A: 当项目仅使用MySQL且需要MySQL特有功能时(如多查询、异步查询)。
Q: 如何获取最后插入的ID?
A: 使用$mysqli->insert_id
属性(面向对象)或mysqli_insert_id($conn)
函数(面向过程)。
Q: 为什么预处理语句更安全?
A: 因为参数与SQL指令分离,防止恶意SQL代码被执行。
进阶主题[编辑 | 编辑源代码]
存储过程调用[编辑 | 编辑源代码]
<?php
$stmt = $mysqli->prepare("CALL get_user_by_id(?)");
$stmt->bind_param("i", $userId);
$stmt->execute();
$result = $stmt->get_result();
?>
元数据查询[编辑 | 编辑源代码]
获取表结构信息:
<?php
$result = $mysqli->query("SHOW COLUMNS FROM users");
while ($row = $result->fetch_assoc()) {
print_r($row);
}
?>
总结[编辑 | 编辑源代码]
MySQLi扩展为PHP开发者提供了强大而灵活的MySQL数据库操作接口。通过结合预处理语句、事务控制和面向对象编程,可以构建安全高效的数据库应用。对于纯MySQL项目,MySQLi通常是比PDO更轻量且功能完整的选择。