經典報錯:
Connection failed: SQLSTATE[HY000] [2002] No such file or directory
**本質:PHP PDO 尋找 MySQL Unix Socket (`mysql.sock`) 路徑與 MySQL 實際生成路徑不一致。** 常見於 macOS (Homebrew/MySQL 官方 pkg)、XAMPP、多 MySQL 實例共存環境。
# 方法 1:查詢運行中的 MySQL 進程
ps aux | grep mysqld
# 看啟動參數 --socket=/xxx/mysql.sock
# 方法 2:MySQL 客戶端查詢
mysql -u root -p -e "SHOW VARIABLES LIKE 'socket';"
# 輸出例:/tmp/mysql.sock 或 /var/lib/mysql/mysql.sock 或 /opt/homebrew/var/mysql/mysql.sock
# 方法 3:全盤搜索 (較慢)
sudo find / -name 'mysql.sock' 2>/dev/null
php -i | grep 'default_socket'
# 輸出例:
# pdo_mysql.default_socket => /var/mysql/mysql.sock => /var/mysql/mysql.sock
# mysqli.default_socket => /var/mysql/mysql.sock => /var/mysql/mysql.sock
# mysql.default_socket => /var/mysql/mysql.sock => /var/mysql/mysql.sock
; 找到 php.ini 路徑
php --ini
; 輸出: Loaded Configuration File => /usr/local/php/etc/php.ini
; 編輯 php.ini,設置三個 socket 參數為第一步找到的真實路徑
; 例:實際為 /tmp/mysql.sock
pdo_mysql.default_socket = /tmp/mysql.sock
mysqli.default_socket = /tmp/mysql.sock
mysql.default_socket = /tmp/mysql.sock ; 兼容舊 mysql_* 函數 (已棄用)
; 重啟 PHP-FPM / Apache
systemctl restart php-fpm
# 或
kill -USR2 `cat /usr/local/php/var/run/php-fpm.pid`
# Homebrew MySQL 默認 socket:/tmp/mysql.sock
# 但 PHP 預設常找 /var/mysql/mysql.sock
# 解決:建立軟連結 (最省事,無需改 php.ini)
sudo mkdir -p /var/mysql
sudo ln -s /tmp/mysql.sock /var/mysql/mysql.sock
# 或改 php.ini (推薦,顯式明確)
pdo_mysql.default_socket = /tmp/mysql.sock
# XAMPP socket 通常在:
/Applications/XAMPP/xamppfiles/var/mysql/mysql.sock (macOS)
/opt/lampp/var/mysql/mysql.sock (Linux)
C:\xampp\mysql\data\mysql.sock (Windows 無 socket 概念,用 TCP)
# php.ini 設置:
pdo_mysql.default_socket = /Applications/XAMPP/xamppfiles/var/mysql/mysql.sock
# my.cnf 指定 socket
[mysqld]
socket = /data/mysql/3306/mysql.sock
port = 3306
[client]
socket = /data/mysql/3306/mysql.sock # 客戶端默認連這個
# PHP 必須同步設置
pdo_mysql.default_socket = /data/mysql/3306/mysql.sock
<?php
// DSN 使用 127.0.0.1 而非 localhost,強制走 TCP/IP (默認 3306 端口)
$dsn = "mysql:host=127.0.0.1;dbname=test;charset=utf8mb4";
// 或顯式指定端口
$dsn = "mysql:host=127.0.0.1;port=3306;dbname=test;charset=utf8mb4";
$pdo = new PDO($dsn, 'user', 'pass');
?>
**原理:** `localhost` 在 PDO/MySQL 客戶端庫中特殊處理為 Unix Socket;`127.0.0.1` 則解析為 TCP 連接。**生產環境建議顯式使用 `127.0.0.1` 避免 socket 路徑糾紛**,且便於後續遷移至雲數據庫/讀寫分離中間件。
php -r "
try {
\$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
echo 'Socket 連接成功';
} catch (PDOException \$e) {
echo '失敗: ' . \$e->getMessage();
}
"
搞清「Socket vs TCP」與「配置四路統一」,2002 錯誤將不再出現。