PHP PDO
PDO (PHP Data Objects) 是 PHP 的資料庫抽象層,提供統一的介面存取不同的資料庫。
建立連接
<?php
$dsn = "mysql:host=localhost;dbname=myapp;charset=utf8mb4";
$username = "root";
$password = "secret";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
try {
$pdo = new PDO($dsn, $username, $password, $options);
} catch (PDOException $e) {
throw new Exception("資料庫連接失敗:" . $e->getMessage());
}
?>
PDO 選項
| 選項 | 說明 |
|---|---|
PDO::ATTR_ERRMODE | 錯誤處理模式 |
PDO::ATTR_DEFAULT_FETCH_MODE | 預設的取得模式 |
PDO::ATTR_EMULATE_PREPARES | 是否模擬預處理 |
錯誤模式
<?php
// SILENT - 不報錯(預設)
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
// WARNING - 產生警告
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
// EXCEPTION - 拋出例外(推薦)
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
?>
取得模式
<?php
// FETCH_ASSOC - 關聯陣列
$user = $stmt->fetch(PDO::FETCH_ASSOC);
// ['id' => 1, 'name' => 'Alice']
// FETCH_NUM - 數字索引陣列
$user = $stmt->fetch(PDO::FETCH_NUM);
// [0 => 1, 1 => 'Alice']
// FETCH_BOTH - 兩者都有(預設)
$user = $stmt->fetch(PDO::FETCH_BOTH);
// FETCH_OBJ - 物件
$user = $stmt->fetch(PDO::FETCH_OBJ);
// $user->name
// FETCH_CLASS - 指定類別
$stmt->setFetchMode(PDO::FETCH_CLASS, 'User');
$user = $stmt->fetch();
?>
預處理語句
<?php
// 準備語句
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
// 執行
$stmt->execute([1]);
// 取得結果
$user = $stmt->fetch();
// 命名參數
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = :email");
$stmt->execute(['email' => 'alice@example.com']);
?>
綁定參數
<?php
$stmt = $pdo->prepare("INSERT INTO users (name, age) VALUES (:name, :age)");
// bindValue - 綁定值
$stmt->bindValue(':name', 'Alice');
$stmt->bindValue(':age', 25, PDO::PARAM_INT);
$stmt->execute();
// bindParam - 綁定變數參考
$name = 'Bob';
$age = 30;
$stmt->bindParam(':name', $name);
$stmt->bindParam(':age', $age, PDO::PARAM_INT);
$stmt->execute();
?>
取得多筆資料
<?php
$stmt = $pdo->query("SELECT * FROM users");
// fetchAll - 取得所有
$users = $stmt->fetchAll();
// 迭代取得
while ($user = $stmt->fetch()) {
echo $user['name'];
}
// 取得單一欄位
$stmt = $pdo->query("SELECT name FROM users");
$names = $stmt->fetchAll(PDO::FETCH_COLUMN);
// ['Alice', 'Bob', 'Charlie']
// 取得鍵值對
$stmt = $pdo->query("SELECT id, name FROM users");
$users = $stmt->fetchAll(PDO::FETCH_KEY_PAIR);
// [1 => 'Alice', 2 => 'Bob']
?>
交易處理
<?php
try {
$pdo->beginTransaction();
$stmt1 = $pdo->prepare("UPDATE accounts SET balance = balance - ? WHERE id = ?");
$stmt1->execute([100, 1]);
$stmt2 = $pdo->prepare("UPDATE accounts SET balance = balance + ? WHERE id = ?");
$stmt2->execute([100, 2]);
$pdo->commit();
} catch (Exception $e) {
$pdo->rollBack();
throw $e;
}
?>
實用方法
<?php
// 取得最後插入的 ID
$id = $pdo->lastInsertId();
// 取得影響的列數
$count = $stmt->rowCount();
// 取得欄位數
$count = $stmt->columnCount();
// 取得錯誤資訊
$error = $stmt->errorInfo();
// 引用字串(不建議,請用預處理)
$quoted = $pdo->quote("O'Reilly");
?>