从零开始:PHP 连接 MySQL 全攻略
引言
在 Web 开发中,PHP 作为广泛使用的后端语言,与 MySQL 数据库的结合是构建动态网站的核心基础。无论是用户数据存储、内容管理系统还是电商平台,PHP 连接 MySQL 都是实现数据交互的必经之路。本文将从基础到进阶,全面讲解 PHP 连接 MySQL 的方法、安全实践及常见问题解决,帮助开发者快速掌握数据库连接的核心技能。
一、环境准备:确保 PHP 与 MySQL 就绪
在开始连接前,需确认以下环境已配置:
- PHP 环境:安装 PHP 7.0+(推荐 7.4+),并启用
mysqli或pdo_mysql扩展(多数集成环境如 XAMPP、WAMP 已默认开启)。 - MySQL 服务:安装 MySQL 5.7+ 或 MariaDB,确保服务已启动(可通过命令行
mysql -u root -p测试连接)。 - 基础配置:创建测试数据库(如
test_db)和表(如users(id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(50), age INT)),并准备测试账号(如root,密码123456)。
二、PHP 连接 MySQL 的核心方式
1. MySQLi 扩展(MySQL improved)
MySQLi 是 MySQL 官方推荐的增强扩展,支持面向过程和面向对象两种风格,适合 MySQL 5.1+ 版本。
(1)面向过程风格
// 1. 建立连接
$servername = "localhost";
$username = "root";
$password = "123456";
$dbname = "test_db";
// 创建连接
$conn = mysqli_connect($servername, $username, $password, $dbname);
// 检查连接是否成功
if (!$conn) {
die("连接失败: " . mysqli_connect_error());
}
// 2. 执行查询(示例:查询 users 表数据)
$sql = "SELECT name, age FROM users";
$result = mysqli_query($conn, $sql);
// 3. 处理结果集
if (mysqli_num_rows($result) > 0) {
while ($row = mysqli_fetch_assoc($result)) {
echo "姓名:" . $row["name"] . ",年龄:" . $row["age"] . "<br>";
}
} else {
echo "0 条记录";
}
// 4. 关闭连接
mysqli_close($conn);
(2)面向对象风格
// 1. 建立连接
$conn = new mysqli("localhost", "root", "123456", "test_db");
// 检查连接错误
if ($conn->connect_error) {
die("连接失败: " . $conn->connect_error);
}
// 2. 执行查询
$sql = "SELECT name, age FROM users";
$result = $conn->query($sql);
// 3. 处理结果
if ($result->num_rows > 0) {
while ($row = $result->fetch_assoc()) {
echo "姓名:" . $row["name"] . ",年龄:" . $row["age"] . "<br>";
}
}
// 4. 关闭连接
$conn->close();
2. PDO 扩展(PHP Data Objects)
PDO 是 PHP 数据对象的通用接口,支持多种数据库(如 MySQL、PostgreSQL),且语法更统一,推荐优先使用。
// 1. 建立连接(DSN:数据源名称)
try {
$dsn = "mysql:host=localhost;dbname=test_db;charset=utf8mb4";
$username = "root";
$password = "123456";
$conn = new PDO($dsn, $username, $password);
// 设置错误模式为异常(便于调试)
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
die("连接失败: " . $e->getMessage());
}
// 2. 执行查询(预处理语句,防止 SQL 注入)
$sql = "SELECT name, age FROM users WHERE age > :age"; // 命名参数 :age
$stmt = $conn->prepare($sql);
$stmt->bindParam(':age', $age, PDO::PARAM_INT); // 绑定参数
$age = 18; // 示例参数
$stmt->execute();
// 3. 获取结果
$users = $stmt->fetchAll(PDO::FETCH_ASSOC); // 获取所有结果为数组
foreach ($users as $user) {
echo "姓名:" . $user["name"] . ",年龄:" . $user["age"] . "<br>";
}
// 4. 关闭连接(PDO 会自动关闭,无需手动操作)
$conn = null;
三、安全实践:避免 SQL 注入与敏感信息泄露
1. 禁用 mysql_* 函数(已过时且不安全)
绝对禁止使用 mysql_query() 等旧函数,因其不支持预处理,易导致 SQL 注入。优先使用 mysqli 或 PDO 的预处理语句。
2. 使用预处理语句(Prepared Statements)
预处理语句通过参数化查询,将 SQL 模板与数据分离,从根本上防止注入攻击:
// MySQLi 预处理示例
$stmt = $conn->prepare("INSERT INTO users (name, age) VALUES (?, ?)");
$stmt->bind_param("si", $name, $age); // "si" 表示字符串+整数类型
$name = "张三";
$age = 25;
$stmt->execute();
// PDO 预处理示例
$stmt = $conn->prepare("INSERT INTO users (name, age) VALUES (:name, :age)");
$stmt->execute([':name' => "李四", ':age' => 30]);
3. 密码与敏感信息管理
- 避免硬编码密码:使用配置文件或环境变量存储,如:
// config.php <?php return [ 'db' => [ 'host' => 'localhost', 'user' => 'root', 'pass' => getenv('DB_PASSWORD'), // 从环境变量读取 'dbname' => 'test_db' ] ]; - 限制数据库权限:为应用账号分配最小权限(如仅
SELECT/INSERT权限),避免root账号直接用于应用。
四、常见问题与解决方案
1. 连接失败:检查服务与配置
- 问题:
Access denied for user 'root'@'localhost' - 解决:确认 MySQL 服务已启动(命令行
net start mysql),检查用户密码是否正确,或尝试重置密码。
2. 中文乱码:设置字符集
- 问题:数据库返回中文显示为乱码(如
????) -
解决:连接后立即设置字符集:
// MySQLi mysqli_set_charset($conn, "utf8mb4"); // utf8mb4 支持所有 Unicode 字符 // PDO $dsn = "mysql:host=localhost;dbname=test_db;charset=utf8mb4";
3. 查询结果为空:检查 SQL 语法与条件
- 问题:执行
SELECT后无数据返回 - 解决:通过
var_dump(mysqli_num_rows($result))确认行数,检查WHERE条件是否正确,或直接打印 SQL 语句调试:echo $sql; // 输出 SQL 语句,在 MySQL 客户端执行验证
五、进阶应用:从连接到数据交互
示例:用户登录功能(安全版)
// 1. 连接数据库
$conn = new mysqli("localhost", "app_user", "secure_pass", "test_db");
if ($conn->connect_error) die("连接失败: " . $conn->connect_error);
// 2. 获取用户输入
$username = $_POST['username'];
$password = $_POST['password'];
// 3. 预处理查询(防止注入)
$stmt = $conn->prepare("SELECT id, name FROM users WHERE username = ?");
$stmt->bind_param("s", $username);
文章版权声明:除非注明,否则均为Dark零点博客原创文章,转载或复制请以超链接形式并注明出处。

