首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 連接 MySQL 核心擴展函數速查:mysql/mysqli/PDO 三代 API 對比

     編輯:PHP 綜合知識

前言

PHP 連接 MySQL 歷經三代 API:mysql_* (已移除)、mysqli (增強)、PDO (抽象層)。本文速查核心函數、預處理、事務、錯誤處理對比。

一、三代 API 狀態

擴展PHP 版本狀態推薦度
mysql≤ 5.6已移除 (7.0+)❌ 禁用
mysqli5.0+維護中✅ 僅 MySQL 專用項目
PDO5.1+維護中✅✅ 首選 (跨庫、預處理、現代)

二、核心流程對比

1. 連接

set_charset('utf8mb4');

// PDO (推薦)
$pdo = new PDO('mysql:host=localhost;dbname=db;charset=utf8mb4', 'user', 'pass', [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_EMULATE_PREPARES => false,
]);

2. 查詢 (有結果集)

query('SELECT * FROM users');
while ($row = $res->fetch_assoc()) { ... }
$res->free();

// PDO
$stmt = $pdo->query('SELECT * FROM users');
while ($row = $stmt->fetch()) { ... }
// 無需顯式釋放,變量銷毀自動釋放

3. 執行 (無結果集: INSERT/UPDATE/DELETE)

query("INSERT INTO users (name) VALUES ('test')");
$id = $mysqli->insert_id;
$affected = $mysqli->affected_rows;

// PDO
$pdo->exec("INSERT INTO users (name) VALUES ('test')");
$id = $pdo->lastInsertId();
$affected = $stmt->rowCount(); // 需用 exec 或 prepare+execute

4. 預處理語句 (核心防注入)

prepare('SELECT * FROM users WHERE id = ? AND status = ?');
$stmt->bind_param('ii', $id, $status); // 類型: i/d/s/b
$stmt->execute();
$res = $stmt->get_result();
while ($row = $res->fetch_assoc()) { ... }
$stmt->close();

// PDO
$stmt = $pdo->prepare('SELECT * FROM users WHERE id = :id AND status = :status');
$stmt->execute([':id' => $id, ':status' => $status]);
while ($row = $stmt->fetch()) { ... }

5. 事務處理

begin_transaction();
try {
    $mysqli->query("INSERT ...");
    $mysqli->query("UPDATE ...");
    $mysqli->commit();
} catch (Exception $e) {
    $mysqli->rollback();
    throw $e;
}

// PDO
$pdo->beginTransaction();
try {
    $pdo->exec("INSERT ...");
    $pdo->exec("UPDATE ...");
    $pdo->commit();
} catch (Exception $e) {
    $pdo->rollBack();
    throw $e;
}

6. 錯誤處理

query("...") or throw new Exception($mysqli->error);

// PDO (異常模式 - 推薦)
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
try {
    $pdo->query("...");
} catch (PDOException $e) {
    error_log($e->getMessage());
    // 用戶友好提示
}

三、結果集處理函數對比

功能mysqlmysqliPDO
獲取關聯陣列mysql_fetch_assoc$res->fetch_assoc()$stmt->fetch(PDO::FETCH_ASSOC)
獲取數字索引陣列mysql_fetch_row$res->fetch_row()$stmt->fetch(PDO::FETCH_NUM)
獲取對象mysql_fetch_object$res->fetch_object()$stmt->fetch(PDO::FETCH_OBJ)
獲取所有無 (需循環)$res->fetch_all(MYSQLI_ASSOC)$stmt->fetchAll()
字段數mysql_num_fields$res->field_count$stmt->columnCount()
行數mysql_num_rows$res->num_rows$stmt->rowCount() (僅緩衝查詢準確)
移動指針mysql_data_seek$res->data_seek()不支援 (改用 fetchAll)
獲取單值mysql_result$res->fetch_column()$stmt->fetchColumn()

四、mysqli 面向過程 vs 面向對象

函數名對應規律:mysqli_function($link, ...) ↔ $mysqli->function(...)。建議統一使用面向對象風格,代碼更清晰、IDE 提示更好。

五、PDO 進階技巧

  1. 調試 SQL:$stmt->debugDumpParams() 查看綁定參數
  2. 異步查詢:PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => false (需 mysqlnd)
  3. 多語句:PDO::MYSQL_ATTR_MULTI_STATEMENTS => true (慎用)
  4. 獲取元數據:$stmt->getColumnMeta($i)

六、遷移建議

  1. 舊專案 mysql_* → mysqli:語法相近,機械替換 + 加預處理
  2. 新專案直接用 PDO:統一介面、支援 SQLite/PostgreSQL/Oracle 遷移
  3. 封裝 Database 類:隱藏底層 API,業務代碼調用 db->query()/db->execute()
  4. 啟用嚴格錯誤模式:開發期拋出異常,生產期記錄日誌

總結

mysql_* 歷史使命結束,mysqli 適合純 MySQL 高性能場景,PDO 以統一介面、真實預處理、跨數據庫、異常處理成為現代 PHP 專案首選。核心原則:永遠使用預處理語句,永不拼接 SQL。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved