从零开始:PHP 连接 MySQL 全攻略

2025-12-17 8180阅读

引言

在 Web 开发中,PHP 作为广泛使用的后端语言,与 MySQL 数据库的结合是构建动态网站的核心基础。无论是用户数据存储、内容管理系统还是电商平台,PHP 连接 MySQL 都是实现数据交互的必经之路。本文将从基础到进阶,全面讲解 PHP 连接 MySQL 的方法、安全实践及常见问题解决,帮助开发者快速掌握数据库连接的核心技能。

一、环境准备:确保 PHP 与 MySQL 就绪

在开始连接前,需确认以下环境已配置:

  1. PHP 环境:安装 PHP 7.0+(推荐 7.4+),并启用 mysqlipdo_mysql 扩展(多数集成环境如 XAMPP、WAMP 已默认开启)。
  2. MySQL 服务:安装 MySQL 5.7+ 或 MariaDB,确保服务已启动(可通过命令行 mysql -u root -p 测试连接)。
  3. 基础配置:创建测试数据库(如 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 注入。优先使用 mysqliPDO 的预处理语句。

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零点博客原创文章,转载或复制请以超链接形式并注明出处。

目录[+]