引言:
PHP 调用 MySQL 数据库主要通过 MySQLi 和 PDO_MySQL 两种扩展实现。本文系统讲解环境配置、连接管理、SQL 语句执行、预处理语句防护 SQL 注入、错误处理机制及 SSL 加密连接等核心内容,帮助 PHP 开发者安全高效地操作 MySQL 数据库。
PHP 的 MySQL 数据库调用完全指南
PHP 与 MySQL 是 Web 开发领域的经典组合,两者配合默契,共同支撑着无数动态网站和应用。在 PHP 中操作 MySQL 数据库,主要通过两种官方推荐的扩展来实现:MySQLi 和 PDO_MySQL。本文将系统讲解从环境配置到连接操作,再到数据增删改查和安全实践的完整流程。
一、环境准备:安装必要组件
在开始之前,确保你的 PHP 环境已经安装了 MySQL 数据库和相应的 PHP 扩展。
Ubuntu/Debian 系统
1 2 3 4 5 6
| sudo apt update sudo apt install apache2 mysql-server php php-mysql libapache2-mod-php
sudo systemctl restart apache2
|
验证扩展安装
正常输出应包含 mysqli 和 pdo_mysql,表示扩展已成功安装。
二、两种主流连接方式
PHP 提供两种官方推荐的 MySQL 连接方式:MySQLi(MySQL Improved)和 PDO(PHP Data Objects)。两者各有优势,选择取决于具体需求。
方案一:MySQLi 扩展
MySQLi 是专门为 MySQL 设计的扩展,支持面向过程和面向对象两种编程风格。
特点:
- 支持 MySQL 特定的高级功能(如多语句执行、事务支持)
- 提供面向过程和面向对象两种接口
- 性能优秀,是 MySQL 专属的解决方案
示例:使用 MySQLi 面向对象方式连接:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <?php $servername = "localhost"; $username = "your_username"; $password = "your_password"; $dbname = "your_database";
$conn = new mysqli($servername, $username, $password, $dbname);
if ($conn->connect_error) { die("连接失败: " . $conn->connect_error); } echo "连接成功";
$conn->close(); ?>
|
示例:使用 MySQLi 面向过程方式连接:
1 2 3 4 5 6 7 8 9 10
| <?php $conn = mysqli_connect($servername, $username, $password, $dbname);
if (!$conn) { die("连接失败: " . mysqli_connect_error()); } echo "连接成功";
mysqli_close($conn); ?>
|
方案二:PDO_MySQL 扩展
PDO 是 PHP 提供的数据库抽象层,支持多种数据库系统(MySQL、PostgreSQL、SQLite 等),代码迁移性更好。
特点:
- 统一的 API 接口,可平滑切换数据库
- 提供更好的异常处理机制(try-catch)
- 支持命名参数,代码可读性更高
- 是跨数据库项目的首选方案
示例:使用 PDO 连接 MySQL:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <?php $servername = "localhost"; $username = "your_username"; $password = "your_password"; $dbname = "your_database";
try { $conn = new PDO( "mysql:host=$servername;dbname=$dbname;charset=utf8mb4", $username, $password ); $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); echo "连接成功"; } catch(PDOException $e) { echo "连接失败: " . $e->getMessage(); }
$conn = null; ?>
|
两种方式对比
| 特性 |
MySQLi |
PDO |
| 数据库支持 |
仅 MySQL |
支持 12+ 种数据库 |
| 编程风格 |
面向对象 + 面向过程 |
仅面向对象 |
| 预处理语句 |
支持 |
支持 |
| 命名参数 |
不支持 |
支持 |
| 异常处理 |
需手动配置 |
原生支持 |
| 适用场景 |
MySQL 专属项目 |
跨数据库项目 |
三、核心数据库操作
查询数据(SELECT)
MySQLi 查询示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <?php $conn = new mysqli($servername, $username, $password, $dbname);
if ($conn->connect_error) { die("连接失败: " . $conn->connect_error); }
$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"] . " - Name: " . $row["name"] . " - Email: " . $row["email"] . "<br>"; } } else { echo "0 条结果"; }
$conn->close(); ?>
|
PDO 查询示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <?php try { $conn = new PDO("mysql:host=$servername;dbname=$dbname;charset=utf8", $username, $password); $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $sql = "SELECT id, name, email FROM Users"; $stmt = $conn->query($sql); while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { echo "ID: " . $row['id'] . " - Name: " . $row['name'] . " - Email: " . $row['email'] . "<br>"; } } catch (PDOException $e) { echo "查询失败: " . $e->getMessage(); } ?>
|
插入数据(INSERT)
使用 MySQLi 插入数据:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <?php $conn = new mysqli($servername, $username, $password, $dbname);
if ($conn->connect_error) { die("连接失败: " . $conn->connect_error); }
$sql = "INSERT INTO Users (name, email) VALUES ('张三', 'zhangsan@example.com')";
if ($conn->query($sql) === TRUE) { echo "新记录插入成功,ID 为: " . $conn->insert_id; } else { echo "错误: " . $conn->error; }
$conn->close(); ?>
|
使用 PDO 插入数据:
1 2 3 4 5 6 7 8 9 10 11 12
| <?php try { $conn = new PDO("mysql:host=$servername;dbname=$dbname;charset=utf8", $username, $password); $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $sql = "INSERT INTO Users (name, email) VALUES ('李四', 'lisi@example.com')"; $conn->exec($sql); echo "新记录插入成功,ID 为: " . $conn->lastInsertId(); } catch (PDOException $e) { echo "插入失败: " . $e->getMessage(); } ?>
|
更新数据(UPDATE)
1 2 3 4 5 6 7 8 9 10 11 12
| <?php
$sql = "UPDATE Users SET email='newemail@example.com' WHERE id=1"; if ($conn->query($sql) === TRUE) { echo "记录更新成功,影响行数: " . $conn->affected_rows; }
$sql = "UPDATE Users SET email='newemail@example.com' WHERE id=1"; $rows = $conn->exec($sql); echo "记录更新成功,影响行数: $rows"; ?>
|
删除数据(DELETE)
1 2 3 4 5 6 7 8 9 10 11 12
| <?php
$sql = "DELETE FROM Users WHERE id=1"; if ($conn->query($sql) === TRUE) { echo "记录删除成功,影响行数: " . $conn->affected_rows; }
$sql = "DELETE FROM Users WHERE id=1"; $rows = $conn->exec($sql); echo "记录删除成功,影响行数: $rows"; ?>
|
四、预处理语句与 SQL 注入防护
预处理语句(Prepared Statements)是防御 SQL 注入攻击的标准做法。
MySQLi 预处理语句
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <?php $conn = new mysqli($servername, $username, $password, $dbname);
if ($conn->connect_error) { die("连接失败: " . $conn->connect_error); }
$stmt = $conn->prepare("INSERT INTO Users (name, email) VALUES (?, ?)");
$stmt->bind_param("ss", $name, $email);
$name = "王五"; $email = "wangwu@example.com"; $stmt->execute();
echo "新记录插入成功,ID 为: " . $stmt->insert_id;
$stmt->close(); $conn->close(); ?>
|
PDO 预处理语句
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <?php try { $conn = new PDO("mysql:host=$servername;dbname=$dbname;charset=utf8", $username, $password); $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $stmt = $conn->prepare("INSERT INTO Users (name, email) VALUES (:name, :email)"); $name = "赵六"; $email = "zhaoliu@example.com"; $stmt->execute([':name' => $name, ':email' => $email]); echo "新记录插入成功,ID 为: " . $conn->lastInsertId(); } catch (PDOException $e) { echo "插入失败: " . $e->getMessage(); } ?>
|
使用预处理语句查询
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <?php
$stmt = $conn->prepare("SELECT id, name, email FROM Users WHERE id > ?"); $stmt->bind_param("i", $minId); $minId = 2; $stmt->execute(); $result = $stmt->get_result();
while ($row = $result->fetch_assoc()) { echo "ID: " . $row["id"] . " - Name: " . $row["name"] . " - Email: " . $row["email"] . "<br>"; } $stmt->close();
$stmt = $conn->prepare("SELECT id, name, email FROM Users WHERE id > :minId"); $stmt->execute([':minId' => 2]); while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { echo "ID: " . $row['id'] . " - Name: " . $row['name'] . " - Email: " . $row['email'] . "<br>"; } ?>
|
五、错误处理与最佳实践
错误处理机制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <?php
if ($conn->connect_error) { die("连接失败: " . $conn->connect_error); }
$result = $conn->query($sql); if (!$result) { echo "查询错误: " . $conn->error; }
try { $conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password); $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } catch (PDOException $e) { echo "连接失败: " . $e->getMessage(); } ?>
|
推荐的最佳实践
| 实践建议 |
说明 |
| 使用预处理语句 |
永远不要直接拼接用户输入到 SQL 中,使用预处理语句防止 SQL 注入 |
| 配置合适的字符集 |
使用 charset=utf8mb4 支持完整的 Unicode 和 Emoji 字符 |
| 密码不要硬编码 |
使用环境变量或配置文件存储数据库密码 |
| 生产环境关闭错误显示 |
使用 error_reporting(0) 避免暴露敏感信息 |
| 设置合理的连接超时 |
避免长时间等待无法响应的数据库连接 |
| 使用连接池或持久连接 |
减少频繁创建和销毁连接的开销 |
环境变量配置示例
1 2 3 4 5 6 7
| <?php
$host = getenv('DB_HOST') ?: 'localhost'; $dbname = getenv('DB_NAME') ?: 'myapp'; $user = getenv('DB_USER') ?: 'appuser'; $pass = getenv('DB_PASS') ?: ''; ?>
|
六、SSL 加密连接
对于生产环境,建议使用 SSL/TLS 加密连接以保护数据传输安全。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| <?php
$conn = mysqli_init();
mysqli_ssl_set( $conn, null, null, "/path/to/ca-cert.pem", null, null );
mysqli_real_connect( $conn, $host, $username, $password, $dbname, 3306, MYSQLI_CLIENT_SSL );
if (mysqli_connect_errno($conn)) { die("SSL 连接失败: " . mysqli_connect_error()); } ?>
|
总结
PHP 与 MySQL 的配合使用是 Web 开发中的标准实践,核心要点可归纳为:
- 选择扩展:MySQLi 适合专属 MySQL 项目,PDO 适合跨数据库或需要更高抽象层的情况
- 安全第一:始终使用预处理语句防止 SQL 注入,合理配置字符集和错误处理
- 连接配置:密码避免硬编码,生产环境使用 SSL 加密连接
掌握这些基础操作后,就可以进一步学习事务处理、存储过程调用、批量操作等高级特性,构建出更强大、安全的 Web 应用。