前言
PHP 連接 MySQL 是後端開發第一課。本文從 php.ini 環境設定、連線函式對照、完整測試代碼、編碼處理、常見錯誤排查,提供完整上手指南。
⚠️ 重要:mysql_* 函式 PHP 7.0+ 已移除。本文保留舊版教學內容並對照 mysqli、PDO 現代寫法。
一、環境檢查與啟用擴展
Windows (XAMPP/WAMP/手動安裝)
- 確認
php_mysqli.dll、php_pdo_mysql.dll 存在於 ext/
- 編輯
php.ini,移除分號:
extension=mysqli
extension=pdo_mysql
- 重啟 Apache
- 驗證:
php -m | findstr mysql 或 phpinfo() 搜尋 mysqli/pdo_mysql
Linux (Ubuntu/Debian/CentOS)
# Ubuntu/Debian
sudo apt-get install php-mysql php-pdo-mysql
sudo systemctl restart apache2 # 或 php7.4-fpm
# CentOS/RHEL
sudo yum install php-mysqlnd php-pdo
sudo systemctl restart httpd # 或 php-fpm
二、三種連線方式對照
| 特性 | mysql_* (舊/已移除) | mysqli (程序/物件) | PDO (推薦) |
| PHP 版本 | ≤ 5.6 | 5.0+ | 5.1+ |
| 資料庫支援 | 僅 MySQL | 僅 MySQL | 多種 (MySQL, PostgreSQL, SQLite...) |
| 預處理語句 | 不支援 | 支援 | 支援 (核心優勢) |
| 物件導向 | 無 | 有 | 有 |
| 異常處理 | 無 | 可選 | 標準 Exception |
| 參數綁定 | 無 | bind_param | execute([...]) |
| 多結果集 | 無 | 支援 | 支援 (nextRowset) |
三、完整測試代碼:mysqli 版 (程序式)
<?php
header("Content-Type: text/html; charset=utf-8");
$host = 'localhost';
$user = 'root';
$pass = '123456789';
$dbname = 'web';
$link = @mysqli_connect($host, $user, $pass, $dbname);
if (!$link) {
die('連線伺服器失敗: ' . mysqli_connect_error());
}
if (!mysqli_set_charset($link, 'utf8mb4')) {
die('設定 utf8mb4 失敗: ' . mysqli_error($link));
}
echo "✅ 連線成功!
";
// 測試查詢
$result = mysqli_query($link, "SELECT VERSION() as version");
$row = mysqli_fetch_assoc($result);
echo "MySQL 版本: {$row['version']}
";
mysqli_free_result($result);
mysqli_close($link);
?>
四、完整測試代碼:mysqli 版 (物件導向)
<?php
header("Content-Type: text/html; charset=utf-8");
$mysqli = new mysqli('localhost', 'root', '123456789', 'web');
if ($mysqli->connect_errno) {
die('連線失敗: ' . $mysqli->connect_error);
}
$mysqli->set_charset('utf8mb4');
echo "✅ 連線成功!
";
$result = $mysqli->query("SELECT VERSION() as version");
$row = $result->fetch_assoc();
echo "MySQL 版本: {$row['version']}
";
$result->free();
$mysqli->close();
?>
五、完整測試代碼:PDO 版 (現代標準)
<?php
header("Content-Type: text/html; charset=utf-8");
$dsn = "mysql:host=localhost;dbname=web;charset=utf8mb4";
$user = 'root';
$pass = '123456789';
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,
]);
echo "✅ PDO 連線成功!
";
$stmt = $pdo->query("SELECT VERSION() as version");
$row = $stmt->fetch();
echo "MySQL 版本: {$row['version']}
";
} catch (PDOException $e) {
die('連線失敗: ' . $e->getMessage());
}
?>
六、編碼設定三要素一致性原則
| 層級 | 設定 | 檢查指令 |
| 資料庫 | CREATE DATABASE ... CHARSET utf8mb4 | SHOW CREATE DATABASE db_name; |
| 資料表 | CREATE TABLE ... CHARSET utf8mb4 | SHOW CREATE TABLE tbl_name; |
| 欄位 | VARCHAR(...) CHARSET utf8mb4 | SHOW FULL COLUMNS FROM tbl; |
| 連線 | mysqli_set_charset / DSN charset | SELECT @@character_set_connection; |
| HTML 頁面 | <meta charset="utf-8"> | 瀏覽器開發工具 Network → Response Headers |
| PHP 檔案 | 以 UTF-8 無 BOM 儲存 | 編輯器右下角確認 |
黃金法則:資料庫、表、欄位、連線、頁面、檔案 全部 UTF-8 (utf8mb4),亂碼問題 99% 解決。
七、常見錯誤完整排查表
| 錯誤訊息 | 原因 | 解決 |
| Call to undefined function mysql_connect() | PHP 7+ 已移除 | 改用 mysqli 或 PDO |
| Access denied for user 'root'@'localhost' | 帳號/密碼錯誤、權限不足 | 確認密碼、GRANT 權限、flush privileges |
| Can't connect to MySQL server on 'localhost' | 服務未啟動、埠錯誤、socket 路徑 | systemctl start mysql、檢查 3306、my.cnf socket |
| Unknown database 'web' | 資料庫不存在 | CREATE DATABASE web CHARSET utf8mb4 |
| mysqli::set_charset(): Error | 字元集不支援 | 用 utf8mb4 (需 MySQL 5.5.3+) |
| PDOException: could not find driver | pdo_mysql 未安裝/啟用 | 安裝 php-pdo-mysql、啟用 extension |
| Server sent charset unknown to the client | 舊版 libmysqlclient | 升級 PHP/MySQL、或連線指定 charset |
八、連線池與持久連線 (進階)
<?php
// mysqli 持久連線 (前綴 p:)
$mysqli = new mysqli('p:localhost', 'user', 'pass', 'db');
// 或
mysqli_connect('p:localhost', 'user', 'pass', 'db');
// PDO 持久連線
$pdo = new PDO($dsn, $user, $pass, [
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
]);
/* 注意:
- PHP-FPM 多進程下,持久連線可能耗盡 MySQL max_connections
- 建議搭配 ProxySQL / PgBouncer 等中介軟體管理連線池
- 一般 Web 請求壽命短,非持久連線通常足夠
*/
?>
九、安全最佳實務
- 應用程式帳號 僅授必要權限 (SELECT/INSERT/UPDATE/DELETE),無 DROP/ALTER/GRANT
- 密碼 長度 ≥ 20、複雜度高,定期輪換
- 禁用 root 遠端登入:
bind-address = 127.0.0.1
- 使用 預處理語句 防 SQL Injection
- 錯誤訊息 不直接輸出給前端,記錄日誌並回傳通用錯誤
- 生產環境 關閉 PHP 錯誤顯示:
display_errors = Off
十、一鍵驗證腳本 (部署檢查用)
<?php
// db_check.php
$checks = [
'PHP 版本' => PHP_VERSION,
'mysqli 載入' => extension_loaded('mysqli') ? '✅' : '❌',
'pdo_mysql 載入' => extension_loaded('pdo_mysql') ? '✅' : '❌',
];
$dsn = "mysql:host=localhost;dbname=test;charset=utf8mb4";
try {
$pdo = new PDO($dsn, 'test_user', 'test_pass', [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
$checks['PDO 連線'] = '✅';
$checks['MySQL 版本'] = $pdo->query("SELECT VERSION()")->fetchColumn();
$checks['字元集'] = $pdo->query("SELECT @@character_set_connection")->fetchColumn();
} catch (Exception $e) {
$checks['PDO 連線'] = '❌ ' . $e->getMessage();
}
echo "";
print_r($checks);
echo "
";
?>
完成環境設定、選擇現代連線方式、統一編碼、善用預處理語句,即能建立穩健、安全的 PHP-MySQL 連線基礎。
- 上一篇文章: PHP MySQL 與 mysqli 交易處理完整指南:ACID 原則、自動提交陷阱與引擎選擇
- 下一篇文章: PHP MySQL 備份還原分卷處理完整實作:大型資料庫分割壓縮與斷點續傳
Copyright ©
程式碼之家 All Rights Reserved