mysql_connect/mysql_select_db 的棄用時間線與替代方案<?php
$conn = mysql_connect("127.0.0.1", "user", "pass");
mysql_select_db("shop", $conn);
// 執行查詢...
mysql_close($conn);
?>
狀態: PHP 5.5 起棄用,PHP 7.0 完全移除。嚴禁用於新專案。
<?php
$mysqli = mysqli_connect("127.0.0.1", "user", "pass", "shop");
if (!$mysqli) {
die("連線失敗: " . mysqli_connect_error());
}
mysqli_set_charset($mysqli, "utf8mb4");
// 查詢: mysqli_query($mysqli, $sql)
// 關閉: mysqli_close($mysqli);
?>
優點:函式風格熟悉、支援預備陳述式。缺點:非物件導向、錯誤處理分散。
mysql:host=127.0.0.1;port=3306;dbname=shop_db;charset=utf8mb4
host:主機 IP 或域名port:連接埠 (預設 3306,可省略)dbname:資料庫名稱charset:關鍵,直接在 DSN 設定避免後續 SET NAMES 注入風險$options = [
// 錯誤模式:拋出 PDOException,統一 try-catch 處理
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
// 預設擷取模式:關聯陣列 (FETCH_ASSOC),也可用 FETCH_OBJ
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
// 關閉模擬預備陳述式,使用 MySQL 原生 Prepared Statement (安全、效能)
PDO::ATTR_EMULATE_PREPARES => false,
// 持久連線 (視架構評估,預設 false)
// PDO::ATTR_PERSISTENT => true,
// 例外情況下自動回滾 (需搭配交易使用)
// PDO::ATTR_STRINGIFY_FETCHES => false,
];
<?php
// config/database.php
return [
'dsn' => 'mysql:host=127.0.0.1;dbname=shop_db;charset=utf8mb4',
'username' => 'app_user',
'password' => 'secure_password',
'options' => [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
],
];
// bootstrap/db.php
$config = require __DIR__ . '/../config/database.php';
try {
$pdo = new PDO(
$config['dsn'],
$config['username'],
$config['password'],
$config['options']
);
// 可選:設定時區
$pdo->exec("SET time_zone = '+08:00'");
return $pdo;
} catch (PDOException $e) {
// 記錄完整錯誤到日誌系統
error_log("[DB] Connection failed: " . $e->getMessage());
// 使用者端顯示友善訊息
if (php_sapi_name() !== 'cli') {
http_response_code(503);
exit('服務暫時不可用,請稍後再試');
}
throw $e;
}
?>
| 錯誤現象 | 原因 | 解決 |
|---|---|---|
| SQLSTATE[HY000] [2002] Connection refused | MySQL 服務未啟動/host/port 錯誤/防火牆阻擋 | 檢查服務狀態、netstat -an | grep 3306、安全組規則 |
| SQLSTATE[HY000] [1045] Access denied | 帳號密碼錯誤/權限不足/主機白名單限制 | 確認 user@host 權限、FLUSH PRIVILEGES |
| 亂碼 / 儲存 ??? | 字元集不一致 | DSN 加 charset=utf8mb4、資料表/欄位 CHARSET=utf8mb4、連線選項 SET NAMES |
| PDOException: could not find driver | PHP 未安裝 pdo_mysql 擴充套件 | 安裝 php-pdo_mysql (Linux) / 開啟 extension=pdo_mysql (Windows php.ini) |
getPdo() 工廠函式/容器綁定,避免重複連線。.env 或 config/,絕不寫死在程式碼。display_errors=Off,例外內容僅寫入日誌。資料庫連線是應用程式的生命線。採用 PDO + 完善的錯誤處理 + 設定外部化 + 最小權限,能為後續開發奠定穩固、安全、可維護的基礎。下一課將進入「資料庫讀取與預備陳述式」實戰。