thinkphp 6+ 数据库连接需严格遵循三层结构:配置文件必须用 connections 数组包裹连接项,default 指向其中已定义键名;db::connect() 仅接受预定义连接名;模型 $connection 属性首次实例化即锁定,动态切换须用 db::connect() 链式调用;敏感信息必须通过 .env + env() 加载。

新手搭建 ThinkPHP 项目时,数据库连接配不对,模型一调就报错——不是“Connection not found”,就是“SQLSTATE[HY000] [1045] Access denied”。问题往往不在代码逻辑,而在配置结构没踩准框架的识别规则。关键就三点:配置文件层级要对、连接名必须预定义、模型绑定只读一次。
database.php 配置必须用 connections + default 结构
ThinkPHP 6+ 不再认扁平数组,直接写 'type'=>'mysql' 会静默失效。必须把连接信息包进 connections 数组里,并用 default 指定默认连接键名:
-
connections 是必填的关联数组,每个子项代表一个完整连接,键名(如
'mysql')后续会被Db::connect('mysql')或模型$connection引用 -
default 必须是
connections中已存在的键名,不能是'mysql'以外的字符串,也不能为空 - 敏感字段(如
username、password)务必通过env()读取,例如:'username' => env('DB_USERNAME', 'root') - 字符集建议写
'charset' => 'utf8mb4',避免 emoji 存储异常
Db::connect() 只认预定义连接名,不认数据库名或模型名
传参不是传表名、库名,也不是传模型类名。它只认 database.php 中 connections 下定义好的键名:
- ✅ 正确:
Db::connect('mysql')、Db::connect('log_db') - ❌ 错误:
Db::connect('user')(这是模型名)、Db::connect('thinkphp')(这是库名)、Db::connect('default')(除非你真在 connections 里写了'default'这个键) - 临时调试可用数组传参:
Db::connect(['type'=>'mysql','hostname'=>'127.0.0.1','database'=>'test']),但生产环境禁用——它绕过连接池,每次新建连接
模型中 $connection 属性只在首次实例化时生效
在模型类里写 protected $connection = 'mysql_read'; 是有效的,但要注意它的生命周期:
- 该属性只在模型类第一次被实例化(如
User::find(1))时读取一次,之后改database.php或重载配置都不影响已加载的模型 - 若需动态切换,不要依赖模型属性,改用
Db::connect('xxx')->name('user')->select() - 关联查询(如
User::with('profile'))不会自动跨库——profile模型仍走自己的$connection,TP 不合并跨库结果,得手动查两次再 PHP 合并
优先用 .env 管理环境差异,别硬编码密码
.env 文件的变量优先级高于 database.php,且部署时可单独替换,是安全刚需:
- 根目录下创建
.env,写入:DB_TYPE=mysql<br>DB_HOSTNAME=192.168.1.10<br>DB_DATABASE=app_main<br>DB_USERNAME=app_rw<br>DB_PASSWORD=secr3t123<br>DB_HOSTPORT=3306
- 在
database.php中对应位置用env('DB_USERNAME', 'root'),第二个参数只是开发环境 fallback - CLI 模式下需确认
think\Env::load()已执行,否则env()返回 null,导致连接拒绝
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











