结论:90%的Yii数据库连接失败主因是host=localhost触发PDO强制走Unix socket,而MySQL未启用或路径不匹配;改用127.0.0.1可强制TCP连接,规避该问题。

直接说结论:90% 的 Yii 数据库连接失败,不是密码错、不是库名错,而是 host 写成 localhost 导致 PDO 走了 Unix socket 而非 TCP,跟 MySQL 实际监听方式不匹配。
为什么 localhost 在 Yii 里会连不上,但原生 PDO 可以?
PHP 的 PDO MySQL 驱动对 localhost 有特殊处理:它会强制走本地 socket 文件(如 /tmp/mysql.sock),而不是 TCP/IP。而很多环境(尤其是 macOS、Docker、MAMP/WAMP 默认配置)MySQL 并未启用 socket,或 socket 路径不对,但 127.0.0.1 明确走 TCP,绕过这个坑。
常见现象:PDOException: SQLSTATE[HY000] [2002] No such file or directory 或 Connection refused,但用命令行 mysql -h 127.0.0.1 -u root -p 却能连上。
- 检查你的
config/db.php中dsn字段,把host=localhost改成host=127.0.0.1 - 如果用了非默认端口(比如 MAMP 是 8889),必须显式加
port=8889,否则 PDO 默认用 3306 - macOS 上若坚持用
localhost,得同步配置 PHP 的mysql.default_socket等三项指向正确的 sock 路径(如/Applications/MAMP/tmp/mysql/mysql.sock),但改 IP 更快更稳
dsn 里漏写 port 或 charset 会怎样?
不写 port:PDO 默认连 3306,遇到 XAMPP/MAMP/自定义端口时直接超时;不写 charset:虽然连接成功,但中文存入可能乱码,查询时 WHERE 条件也容易失效(尤其含 emoji 或 utf8mb4 字符)。
-
dsn推荐写全:mysql:host=127.0.0.1;port=3306;dbname=myapp; charset=utf8mb4 -
charset=utf8mb4比utf8更安全,支持 4 字节 Unicode(微信昵称、emoji) - 如果数据库是
utf8mb4_unicode_ci排序规则,charset必须对应,否则 Yii 的 Schema 缓存可能出错
报 SQLSTATE[HY000] [1049] Unknown database 怎么办?
这错误明确告诉你:数据库实例连上了,但指定的库名不存在。不是权限问题,也不是密码错。
- 先确认库是否存在:
mysql -h 127.0.0.1 -u root -p -e "SHOW DATABASES;" | grep your_dbname - 检查
dsn里的dbname拼写,注意大小写 —— Linux 下 MySQL 库名区分大小写,Windows 不区分 - 如果你用的是高级模板(advanced),
db.php可能在environments/dev/common/config/或environments/prod/common/config/下,别改错了文件 - 迁移前没建库?运行
php yii migrate/create init不会自动建库,得手动CREATE DATABASE `your_dbname` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
测试连接是否真通,别只信 php yii migrate
php yii migrate 报错堆栈长,掩盖真正原因。最有效的验证方式是绕过 Yii,用最小上下文测 PDO 是否能握手。
新建一个 test-pdo.php 放在项目根目录:
<?php $dsn = 'mysql:host=127.0.0.1;port=3306;dbname=testdb;charset=utf8mb4';
$user = 'root';
$pass = '123456';
try {
$pdo = new PDO($dsn, $user, $pass, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);
echo "✅ PDO 连接成功\n";
echo "MySQL 版本:" . $pdo->getAttribute(PDO::ATTR_SERVER_VERSION) . "\n";
} catch (PDOException $e) {
echo "❌ 连接失败:" . $e->getMessage() . "\n";
}
这个脚本能快速定位是 Yii 配置问题,还是底层环境(PHP 扩展、MySQL 服务、网络)问题。很多情况下,Yii 报错只是“下游故障”的表象,真正卡点在 socket 路径、防火墙、或 MySQL 未 bind 到 127.0.0.1。
真正麻烦的从来不是“连不上”,而是“连上了但查不出数据”——那大概率是 charset 和表实际编码不一致,或者 migration 生成的表用了 utf8 而不是 utf8mb4,这种细节在日志里不报错,只默默丢数据。











