db::connect() 必须传 config/database.php 中 connections 数组预定义的合法连接名,如 'log_db';该名仅支持小写字母、数字、下划线,且对应连接块须含 type、hostname、database、username、password 四项,connections 必须位于配置文件顶层。

Db::connect() 调用必须传预定义连接名,不能传数据库名或模型名
ThinkPHP 多库配置不是“写完就能用”,关键在于 config/database.php 中的 connections 数组是否被正确识别。框架只从这个数组里取键名,Db::connect('log_db') 里的 'log_db' 必须是 connections 下的一个合法 key。传 'user_db' 却没在配置里声明?直接抛 Connection not found: user_db。这不是代码写错了,是配置漏了。
- 连接名只能是小写字母、数字、下划线,禁止点号(
'log.db'❌)、大写('LogDB'❌)、空格或特殊符号 - 每个连接块必须显式包含
'type',比如'mysql'或'pgsql';漏掉会触发Class 'PDO' not found类错误,因为框架根本没加载对应驱动 -
'hostname'、'database'、'username'、'password'四项缺一不可,'charset'和'prefix'建议显式写死,避免环境差异导致中文乱码或表名拼错
connections 数组必须写在 config/database.php 的顶层结构里
config/database.php 返回的是一个 PHP 数组,connections 是其中一级键,不能嵌套在其他字段下。常见翻车写法:把整个多库配置包进 'mysql' => [...] 里,或者误塞进 'params'、'options' 这类二级字段中——框架完全无视。
- 正确位置:和
'default'同级,直接作为 return 数组的 key - 错误示例:
'connections' => ['mysql' => [...]]写在某个子数组里,或被注释块意外包裹 - 修改后务必执行
php think clear:config,否则缓存未刷新,新配置不生效
Db::connect() 返回的是独立 Query 实例,链式操作不会自动继承上下文
调用 Db::connect('slave_db') 后得到一个 Query 对象,后续所有 ->table()、->where()、->select() 都走这个连接。但要注意:某些扩展方法(如 ->cache()、->with())内部可能触发默认连接复用逻辑,导致查到主库去。
- 推荐写法:
$db = Db::connect('slave_db'); $db->table('log')->select();—— 显式持有实例,可控性强 - 危险写法:
Db::connect('slave_db')->name('log')->cache()->select()——->cache()可能绕过当前连接上下文 -
->name('log')会自动拼前缀,跨库时容易错成main_db.tp_log;改用->table('log_db.log')更稳妥
模型类绑定连接必须用 protected $connection = 'xxx'
模型默认走 'default' 连接,想让它固定连某个库,不能靠运行时 Db::connect() 切换,而是在模型类里声明 protected $connection = 'log_db';。这个值只在模型初始化时读一次,之后不会随配置变更自动更新。
- 关联查询(
with())不会跨连接路由:User 模型连main_db,关联 Profile 模型连log_db,User::with('profile')仍走 User 的连接,Profile 的$connection不生效 - 事务完全隔离:
Db::connect('a')->startTrans()和Db::connect('b')->startTrans()是两套互不干扰的事务,无法合并提交
.env 无法定义多维连接结构,connections 必须硬编码在 config/database.php
.env 只支持扁平变量(如 DB_HOSTNAME),不能表达数组嵌套。你没法用 env('LOG_DB_HOSTNAME') 动态填充 connections['log_db']['hostname']——框架不解析这种路径式引用。
- 多环境差异只能靠条件判断:在
config/database.php里用env('APP_ENV') === 'prod'手动分支配置 - 若需更高灵活性(如多租户动态库),得用中间件 +
Db::setConnectConfig()注册,而不是依赖.env
最常被忽略的一点:两个连接配了相同 hostname 和 port,却以为它们物理隔离——其实只是逻辑分库,锁表、慢查询、连接数限制全共享。真要分离风险,得部署在不同 MySQL 实例上。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











