ThinkPHP 6 多数据库配置必须严格遵循 connections 预定义 + 显式调用双约束机制:所有连接须在 config/database.php 的 'connections' 中完整定义,键名仅支持小写字母+下划线;Db::connect() 必须显式调用并立即链式使用,模型需通过 protected $connection 指定连接名,跨库操作须用 table() 或原生 SQL,事务与关联查询均不跨连接。

ThinkPHP 6 多数据库配置不是“加几个数组就行”,而是必须严格遵循 connections 预定义 + 显式调用的双约束机制;漏掉任一环节,都会导致查默认库、连错实例、或直接报 Connection not found。
database.php 的 connections 必须完整定义每个连接
TP6 不认 .env 里带编号的多库配置(如 database2.hostname),也不接受运行时传数组。所有连接都得在 config/database.php 的 'connections' 数组里明确定义键名和全部参数。
-
'type'、'hostname'、'database'、'username'、'password'缺一不可;漏掉'type'会导致驱动加载失败,报Class 'PDO' not found - 连接名只能是小写字母+下划线,不能含点号(如
'log.db')、大写字母(如'LogDb')或数字开头,否则Db::connect()直接抛异常 -
'prefix'强烈建议设为空字符串(''),跨库时用table()而非name(),避免前缀拼接污染真实表名 - 不同连接指向同一台 MySQL 实例但库名不同,是合法的;但 hostname/port/database 都写错,就真连到空库或权限拒绝了
Db::connect('xxx') 必须每次显式调用且立即链式使用
Db 是无状态门面,Db::connect('slave_db') 返回的是新实例,不赋值就丢弃——这是最隐蔽的翻车点。
- 错误写法:
Db::connect('log_db'); Db::table('event')->select();→ 第二行仍走default - 正确写法:
Db::connect('log_db')->table('event')->select();或先存变量:$logDb = Db::connect('log_db');,再用$logDb->table(...) - 慎用
name():它依赖模型级prefix,而跨库时 prefix 往往为空,容易误匹配;优先用table('db_name.table')或纯表名 + 独立连接 - 加
->cache()、->useSoftDelete()等中间方法后,底层可能复用连接上下文,导致意外切回 default;封装成独立$db变量更可控
模型类绑定连接必须靠 protected $connection
模型不自动识别库,继承 think\Model 后,默认永远走 default 连接,除非你硬编码指定。
立即学习“PHP免费学习笔记(深入)”;
- 在模型类中写
protected $connection = 'admin_db';,该值会覆盖全局default,且优先级高于任何配置文件设置 -
$connection必须和connections数组里的键**完全一致**(大小写敏感),写成'AdminDb'或'admin-db'都会静默 fallback 到 default -
with()关联查询不会跨库:User 模型连user_db,Profile 模型连profile_db,User::with('profile')只会查 User 表,Profile 仍走它自己的$connection,不会自动合并 - 事务无法跨连接:
Db::connect('a')->startTrans()和Db::connect('b')->startTrans()是两个孤立事务,没原子性保障
跨库 JOIN 只能在同一 MySQL 实例内用原生 SQL
MySQL 本身不支持跨物理实例 JOIN,TP6 也不会帮你做分布式查询合并。所谓“跨库”只有两种可行路径:
- 同一服务器、多数据库:用
Db::connect('mysql')->query("SELECT u.name, l.level FROM user_db.users u JOIN log_db.logs l ON u.id = l.uid"),注意写全db_name.table格式 - 不同服务器:必须分两次查,比如先
Db::connect('user_db')->table('users')->select(),再Db::connect('log_db')->where('uid', 'in', $userIds)->select(),最后 PHP 数组合并 - 别指望
Db::name('users')->alias('u')->join('log_db.logs l', 'u.id=l.uid')能跑通——TP6 的join()底层不解析库名,只拼表名,结果就是Unknown table 'log_db.logs'
真正复杂的地方在于连接名一致性、table() 与 name() 的语义差异、以及事务/缓存等中间操作对连接上下文的隐式干扰——这些细节不写死在代码里,光靠文档说明根本防不住线上连错库。



















