ThinkPHP多数据库需在config/database.php中定义多个唯一键名连接(如'mysql_read'),每个必须显式声明'type'且键名不含点号或大写字母;Db::connect()参数为配置键名而非数据库名,传错抛异常;模型$connection仅初始化时生效,跨库关联须手动分查;环境变量覆盖用DATABASE_X_Y_Z二维语法。

数据库配置文件里怎么写多个连接
ThinkPHP 的多数据库支持靠的是在 config/database.php 里定义多个键名,而不是只留一个 default。每个连接必须有唯一键名(比如 'mysql_read'、'pgsql_log'),且结构和默认连接一致。
常见错误是复制粘贴后忘了改 hostname 或 database,结果两个连接连的其实是同一个库;或者漏掉 'type' 导致框架用默认 mysql 去解析 PostgreSQL 配置,报错 Class 'PDO' not found。
- 所有连接都必须显式声明
'type'(如'mysql'、'pgsql'、'sqlsrv') - 连接名不能含点号或大写字母,否则
Db::connect('log.db')会失败 - 如果某个连接只读不用写,建议把
'write_master'设为false,避免误触发主库写操作
'mysql_write' => [
'type' => 'mysql',
'hostname' => '192.168.1.10',
'database' => 'app_main',
'username' => 'root',
'password' => 'xxx',
],
'mysql_read' => [
'type' => 'mysql',
'hostname' => '192.168.1.11',
'database' => 'app_main',
'username' => 'ro_user',
'password' => 'yyy',
],
Db::connect() 动态切换连接时传什么参数
Db::connect() 的参数不是数据库名,而是配置文件里定义的连接键名(比如 'mysql_read'),它会直接加载对应配置并返回一个新的 Query 对象。传错名会抛出异常 Connection not found: xxx。
注意:这个调用不改变全局默认连接,每次都要显式调用;也不支持运行时修改已创建连接的 host 或 port —— 那些属于配置项,只能在 config 文件或通过环境变量预设。
- 传字符串:
Db::connect('mysql_read')→ 返回只读连接实例 - 传数组:
Db::connect(['type'=>'sqlite','database'=>'/tmp/test.db'])→ 临时连接,不走配置文件 - 不要传模型名或表名,
Db::connect('User')是错的
模型类里指定连接和自动切换的边界在哪
模型类用 protected $connection = 'mysql_read'; 可绑定固定连接,但这个值只在模型首次初始化时读取一次;如果运行中切换了数据库配置(比如 reload config),模型不会自动感知。更关键的是:关联查询(with())默认仍走当前模型的 $connection,不会智能路由到被关联模型的连接上。
容易踩的坑是以为设置了 $connection 就能跨库 join —— 实际上 MySQL 不允许直接 join 不同实例的表,TP 也不会帮你做数据合并,这时候得手动查两次再 PHP 合并。
- 跨库关联必须拆成多次查询,不能依赖
join() -
scope或globalScope中若用了Db::name(),它仍走默认连接,不受模型$connection影响 - 事务只对单个连接有效,
Db::startTrans()无法跨连接保证一致性
env 环境变量覆盖多连接配置的写法
线上不同环境要区分读写库地址?别硬编码进 database.php。ThinkPHP 支持用 .env 覆盖配置,但多连接场景下必须用“二维键名”语法,例如:
DATABASE_MYSQL_WRITE_HOSTNAME=10.0.1.5 DATABASE_MYSQL_READ_HOSTNAME=10.0.1.6 DATABASE_MYSQL_WRITE_DATABASE=prod_main DATABASE_MYSQL_READ_DATABASE=prod_slave
框架会自动把 DATABASE_X_Y_Z 映射成 database.x.y.z,所以最终生效的是 database.mysql_write.hostname。漏掉中间层级(比如写成 DATABASE_MYSQL_WRITEHOST)会导致覆盖失败,还是读 config 文件里的旧值。
- 环境变量名必须全大写,用下划线分隔,且前缀严格为
DATABASE_ - 连接名中的下划线会被转成点号,
mysql_read→mysql.read,所以变量要写DATABASE_MYSQL_READ_XXX - 如果某环境不需要某个连接,直接不设对应 env 变量即可,TP 会 fallback 到 config 文件里的默认值
最常被忽略的是连接池复用问题:多个 Db::connect('xxx') 调用默认共用一个 PDO 实例(只要参数完全相同),但如果在协程环境(Swoole)里没关 'deploy' => 0,可能因连接未释放导致超时。这时候得看具体部署模式,不是配对就能跑通的。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










