yii数据库连接必须注册为db组件并置于config/web.php的components数组内,否则yii::$app->db报“unknown component id: db”;缺host、dbname、username、password任一字段,或charset未设utf8mb4,均导致连接失败。

Yii 的数据库连接不是“连一下就行”,而是必须通过 db 组件注册进应用容器,否则 Yii::$app->db 会直接报 Unknown Component ID: db。配置错位置、漏字段、字符集不匹配,三者占了 90% 的连接失败原因。
db 组件必须放在 config/web.php(或 config/main.php)的 components 数组里
很多人把配置写在 config/db.php 里就以为完事了——但如果不被 components 引用,它根本不会加载。
- 正确做法:在
config/web.php的'components' => [...]中显式写入'db' => require __DIR__ . '/db.php',或者直接把整个数组贴进去 - 错误现场:
'dsn' => 'mysql:host=localhost;dbname=test'直接扔在web.php顶层,没包在'components'里 → 启动即报错 - 高级模板常见结构:配置实际落在
config/main-local.php,由main.phprequire_once引入;该文件通常被.gitignore排除,避免密钥泄露 - 若文件不存在,手动创建,内容必须以
return $config;结尾,否则 Yii 解析失败
四个必填字段缺一不可:host、dbname、username、password
dsn 字段可省略(Yii 会自动拼),但拆成独立键更安全、易调试,尤其在 Docker 或远程环境里。
-
host别写127.0.0.1:本地开发用localhost(走 Unix socket),Docker 容器间通信必须用服务名(如mysql),写127.0.0.1会导致连接绕过 socket 并触发 host 检查失败 -
username和password不能为空字符串;设为''会触发Access denied for user ''@'localhost' -
dbname必须真实存在,且用户有访问权限;报Unknown database就先去 MySQL 里SHOW DATABASES确认 - 敏感信息别硬编码:
'password' => getenv('DB_PASSWORD') ?: 'root'是推荐写法,兼顾本地开发和 CI/CD 安全
charset 必须设为 utf8mb4,且要和 MySQL 实际库表编码一致
设错 charset 不一定立刻报错,但中文插入会截断、emoji 存不进、甚至触发 Incorrect string value。
-
utf8在 Yii 2.0.49 中实际映射为utf8mb3,不支持 emoji;utf8mb4才是完整 Unicode 支持 - 仅配 PHP 层不够:MySQL 服务端、库、表、连接层都得是
utf8mb4;检查命令:SHOW VARIABLES LIKE 'character_set%'; SHOW CREATE TABLE xxx; - 若 MySQL 开启了
STRICT_TRANS_TABLES(新版默认),建议加'initSQLs' => ["SET NAMES utf8mb4"],否则建表或插入时可能静默失败 -
'charset' => 'utf8mb4'写在db配置里即可,不用再塞进dsn—— 重复设置反而可能冲突
连接失败时看不到真实错误?加 PDO::ATTR_ERRMODE
默认 Yii 只抛笼统的 CDbException,真正有用的底层报错(比如 Plugin ‘caching_sha2_password’ is not loaded)被吞掉了。
- 在
db配置里加上:'attributes' => [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION] - 这样 PDO 错误会原样暴露,方便定位是认证插件问题、DNS 解析失败,还是数据库名拼错了
- 这个设置只影响异常路径,不影响正常查询性能
- 顺手检查下 PHP 是否启用了
pdo_mysql扩展:php -m | grep pdo;没启用会报could not find driver,但这其实是 DSN 解析失败的误导提示
最常被跳过的点:main-local.php 文件是否存在、是否被正确引入、结尾是否有 return $config;。这三个条件任意一个不满足,db 组件就等于没注册——后面所有 AR 操作、Gii 生成、Yii::$app->db 调用,全都会崩在第一步。











