PDO (PHP Data Objects) 是 PHP 5.1+ 內置的輕量級、一致性數據庫訪問抽象層。它提供統一的面向對象 API,支持 12+ 種數據庫驅動,是現代 PHP 專案(Laravel、Symfony、ThinkPHP 等)的標準數據庫訪問方式。
PDOException 統一錯誤模型,配合 try-catch 優雅處理。php.ini 啟用擴展即可。; Linux/Unix
extension=pdo.so
extension=pdo_mysql.so ; MySQL 驅動
extension=pdo_pgsql.so ; PostgreSQL
; Windows (php.ini)
extension=php_pdo.dll
extension=php_pdo_mysql.dll
;extension=php_pdo_sqlite.dll
;extension=php_pdo_oci.dll ; Oracle
; ... 其他驅動按需開啟
; 重啟 PHP-FPM / Apache 生效
驗證:php -m | grep pdo 或 phpinfo() 搜尋 "PDO"。
<?php
$dsn = 'mysql:host=localhost;dbname=test;charset=utf8mb4';
$user = 'root';
$pass = '';
try {
$pdo = new PDO($dsn, $user, $pass, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, // 拋出異常
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, // 默認關聯數組
PDO::ATTR_EMULATE_PREPARES => false, // 使用真實預處理
// PDO::ATTR_PERSISTENT => true, // 長連接(慎用)
]);
echo "連接成功<br>";
// 查詢示例
$stmt = $pdo->query("SELECT * FROM users LIMIT 5");
while ($row = $stmt->fetch()) {
print_r($row);
}
} catch (PDOException $e) {
die("Error: " . $e->getMessage());
}
?>
| 方法 | 說明 |
|---|---|
__construct($dsn, $user, $pass, $options) | 建立連接 |
prepare($sql, $options) | 預處理,返回 PDOStatement |
query($sql) | 直接執行 SELECT,返回 PDOStatement |
exec($sql) | 執行 INSERT/UPDATE/DELETE,返回影響行數 |
lastInsertId($seqName) | 獲取自增 ID |
beginTransaction()/commit()/rollBack() | 事務控制 |
quote($str, $type) | 字符串轉義(預處理優先,極少用) |
setAttribute/getAttribute | 設置/獲取連接屬性 |
getAvailableDrivers() | 獲取可用驅動列表 |
| 方法 | 說明 |
|---|---|
execute($params) | 執行預處理語句 |
fetch($mode) | 獲取下一行 |
fetchAll($mode) | 獲取所有行 |
fetchColumn($col) | 獲取單列值 |
fetchObject($class, $args) | 映射到對象/類 |
bindParam($param, &$var, $type) | 綁定參數(引用) |
bindValue($param, $value, $type) | 綁定值 |
rowCount() | 影響行數(SELECT 不可靠) |
setFetchMode($mode) | 設置默認獲取模式 |
debugDumpParams() | 調試輸出 SQL 與參數 |
PDO::FETCH_ASSOC:關聯數組 ['name'=>'Tom'](最常用)。PDO::FETCH_NUM:數值索引 [0=>'Tom']。PDO::FETCH_BOTH:雙模式合併(默認,佔內存)。PDO::FETCH_OBJ:匿名對象 $row->name。PDO::FETCH_CLASS:映射到指定類(屬性名=列名),構造函數在賦值後調用(FETCH_PROPS_LATE 可改)。PDO::FETCH_INTO:更新現有對象實例。PDO::FETCH_COLUMN:只取指定列,配合 fetchAll 得到一維數組。PDO::FETCH_KEY_PAIR:兩列→鍵值對數組 ['id'=>'name']。PDO::FETCH_GROUP:按列分組,常配合 FETCH_COLUMN 或 FETCH_UNIQUE。<?php
// 1. 佔位符:? (位置) 或 :name (命名)
$stmt = $pdo->prepare("INSERT INTO users (name, email, status) VALUES (?, ?, ?)");
$stmt->execute(['Tom', 'tom@example.com', 1]);
// 2. 批量插入:事務 + 預處理循環
$pdo->beginTransaction();
$stmt = $pdo->prepare("INSERT INTO logs (msg, level) VALUES (:msg, :level)");
foreach ($logs as $log) {
$stmt->execute([':msg'=>$log['msg'], ':level'=>$log['level']]);
}
$pdo->commit();
// 3. IN 子句動態綁定
$ids = [1,2,3,4];
$placeholders = implode(',', array_fill(0, count($ids), '?'));
$stmt = $pdo->prepare("SELECT * FROM users WHERE id IN ($placeholders)");
$stmt->execute($ids);
$users = $stmt->fetchAll();
PDO::ERRMODE_SILENT(默認):靜默,需手動檢查 errorCode()/errorInfo()。PDO::ERRMODE_WARNING:觸發 E_WARNING。PDO::ERRMODE_EXCEPTION(推薦):拋出 PDOException,統一 try-catch,配合日誌記錄。charset=utf8mb4,否則中文亂碼。ATTR_EMULATE_PREPARES => false,使用真實預處理,防注入更徹底。ATTR_PERSISTENT 易導致「MySQL server has gone away」、連接洩漏、事務殘留。fetchAll() 計數或 COUNT(*) 查詢。PDO::CURSOR_SCROLL + fetch(PDO::FETCH_ORI_NEXT) 流式處理,避免內存爆炸。PDO 以「統一、安全、面向對象」確立了 PHP 數據庫訪問的工業標準。掌握「連接配置 → 預處理 → 綁定執行 → 靈活獲取 → 異常處理」完整鏈路,並養成「關閉模擬預處理、指定字符集、事務包裹寫操作」的肌肉記憶,是每位 PHP 開發者的必修課。