db::connect() 创建新连接实例而非切换,默认连接不变;必须赋值后显式调用,模型通过 $connection 绑定固定库,配置需预定义且含 database 字段,多租户宜用中间件注册连接。

Db::connect() 不是切换,是新建连接实例
调用 Db::connect('mysql2') 并不会改变默认数据库连接,它只是返回一个全新的 Query 实例。很多人误以为执行完这行代码后,后续所有 Db::table() 都会走新库,结果查的还是默认库。
- 必须把返回值赋给变量,例如:
$logDb = Db::connect('mysql2'); - 之后所有查询必须显式使用该变量:
$logDb->table('log')->select(); - 如果只写
Db::connect('mysql2'); Db::table('log')->select();,第二行仍走默认连接 - 配置名(如
'mysql2')必须提前在config/database.php的connections数组中定义,不能临时传 DSN 或数组(除非你明确要临时连接)
模型类里用 $connection 绑定更稳妥
适合读写分离、日志库、主从等长期固定连接的场景。这个值在模型类加载时读取一次,之后不会响应运行时配置变更,稳定性高。
- 在模型顶部声明:
protected $connection = 'mysql_read';,对应配置里的键名 - 所有操作(
find()、save()、delete()、with())都走该连接 - 关联模型不自动继承父模型的
$connection,若也要走同库,需在关联定义里单独加'connection' => 'mysql_read' - 不要在控制器里动态改
$model->connection = ...,它不生效——这个属性是静态绑定的
配置漏 database 字段导致 “No database selected”
这不是连不上 MySQL 服务,而是连接成功后没指定具体库名。ThinkPHP 不会帮你创建数据库,只负责连接并执行 USE xxx。
- 检查
config/database.php中目标连接配置是否包含'database' => 'my_app_v2',拼写和大小写必须完全一致(Linux 下尤其敏感) - 确认 MySQL 用户对目标库有
SELECT权限,仅能连上hostname不代表能操作库 - 若用了
unix_socket,确保路径真实存在且 PHP 进程可读 - 错误信息
No database selected出现在 SQL 执行前,说明 PDO 已连上但未选库
多租户或高频切换场景别硬套 Db::connect()
每次请求都要根据租户 ID 动态选库时,反复调 Db::connect() 不仅低效,还可能耗尽连接数。中间件注册 + 请求对象挂载才是正解。
- 在中间件中解析租户标识(如子域名),组装连接配置,调用
Db::setConnectConfig('tenant_123', $config)注册 - 再执行
app('request')->db = Db::connect('tenant_123');挂到请求对象上 - 业务代码统一用
$this->request->db->table(...),而不是Db::table() - 事务无法跨
Db::connect()实例,$db1->startTrans()和$db2->startTrans()完全隔离
$connection 是初始化时静态读取的,不是运行时变量;而 Db::connect() 返回的对象如果不存下来、不显式使用,就等于什么都没做。php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











