PHP 连接 MySQL 的 3 种方式:mysql_*、mysqli、PDO 对比与最佳实践

分类:后端开发 时间:2026-02-24 浏览:1
1

一、为什么要淘汰 mysql_* 函数?

mysql_*是 PHP 早期的 MySQL 扩展,存在致命问题:

  1. 不支持预处理语句,易引发 SQL 注入;

  2. 仅支持面向过程编程,代码复用性差;

  3. PHP5.5 起标记为废弃,PHP7.0 完全移除。

二、三种连接方式的代码实现

1. mysql_*(仅作对比,禁止使用)
<?php
// 连接数据库(已废弃)
$conn = mysql_connect("localhost", "root", "");
mysql_select_db("php_demo", $conn);
mysql_set_charset("utf8", $conn);

// 查询数据(存在SQL注入风险)
$id = $_GET['id'];
$sql = "SELECT * FROM users WHERE id = $id";
$result = mysql_query($sql);
$user = mysql_fetch_assoc($result);

print_r($user);
mysql_close($conn);
?>
2. mysqli(面向过程 + 面向对象)
方式 1:面向过程
<?php
// 连接数据库
$conn = mysqli_connect("localhost", "root", "", "php_demo");
if (mysqli_connect_errno()) {
    die("连接失败:" . mysqli_connect_error());
}
mysqli_set_charset($conn, "utf8");

// 预处理语句(防SQL注入)
$id = $_GET['id'];
$stmt = mysqli_prepare($conn, "SELECT * FROM users WHERE id = ?");
mysqli_stmt_bind_param($stmt, "i", $id); // i=整数,s=字符串,d=浮点数
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
$user = mysqli_fetch_assoc($result);

print_r($user);
mysqli_close($conn);
?>
方式 2:面向对象
<?php
// 连接数据库
$mysqli = new mysqli("localhost", "root", "", "php_demo");
if ($mysqli->connect_errno) {
    die("连接失败:" . $mysqli->connect_error);
}
$mysqli->set_charset("utf8");

// 预处理语句
$id = $_GET['id'];
$stmt = $mysqli->prepare("SELECT * FROM users WHERE id = ?");
$stmt->bind_param("i", $id);
$stmt->execute();
$result = $stmt->get_result();
$user = $result->fetch_assoc();

print_r($user);
$mysqli->close();
?>
3. PDO(推荐,支持多数据库)
<?php
// 连接数据库
try {
    $pdo = new PDO(
        "mysql:host=localhost;dbname=php_demo;charset=utf8",
        "root",
        "",
        [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, // 抛出异常
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC // 默认关联数组
        ]
    );
} catch (PDOException $e) {
    die("连接失败:" . $e->getMessage());
}

// 预处理语句(防SQL注入)
$id = $_GET['id'];
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = :id");
$stmt->bindParam(":id", $id, PDO::PARAM_INT);
$stmt->execute();
$user = $stmt->fetch();

print_r($user);
?>

三、三种方式核心对比

表格

特性mysql_*mysqliPDO
预处理语句不支持支持支持
多数据库兼容仅 MySQL仅 MySQLMySQL/PostgreSQL 等
错误处理手动判断异常 / 手动异常 / 错误码
面向对象支持
PHP 版本支持≤5.6≥5.0≥5.1
安全性

四、PDO 最佳实践:封装数据库类

<?php
class DB {
    private static $instance = null;
    private $pdo;

    // 单例模式:避免重复连接数据库
    private function __construct() {
        $dsn = "mysql:host=localhost;dbname=php_demo;charset=utf8";
        $options = [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
            PDO::ATTR_PERSISTENT => true // 长连接,提升性能
        ];
        $this->pdo = new PDO($dsn, "root", "", $options);
    }

    // 获取实例
    public static function getInstance() {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    // 查询单条数据
    public function getOne($sql, $params = []) {
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute($params);
        return $stmt->fetch();
    }

    // 查询多条数据
    public function getAll($sql, $params = []) {
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute($params);
        return $stmt->fetchAll();
    }

    // 新增/修改/删除
    public function exec($sql, $params = []) {
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute($params);
        return $stmt->rowCount(); // 影响行数
    }

    // 获取最后插入的ID
    public function lastInsertId() {
        return $this->pdo->lastInsertId();
    }

    // 禁止克隆
    private function __clone() {}
}

// 使用示例
$db = DB::getInstance();
$user = $db->getOne("SELECT * FROM users WHERE id = ?", [1]);
print_r($user);
?>
 
文章链接:http://www.qwkf.cn//houduan/22.html
文章标题:PHP 连接 MySQL 的 3 种方式:mysql_*、mysqli、PDO 对比与最佳实践

相关阅读