db::connect()在命令行必须显式调用并立即链式使用,否则连接实例丢失,后续db操作仍走default库;模型需硬编码$connection属性,事务无法跨库,内置命令如db:seed仅支持default连接。

命令行下 Db::connect() 必须显式调用且立即链式使用
命令行环境(如 php think command:run)和 Web 请求一样,Db 是无状态门面,不会自动继承配置或缓存连接上下文。你写 Db::connect('log_db') 但不立刻执行查询,这个连接实例就丢了——下一行 Db::table('event') 仍走 default。
常见错误现象:Db::connect('log_db'); Db::table('event')->select(); → 返回的是 default 库里的数据,不是 log_db 的。
- 正确写法必须是
Db::connect('log_db')->table('event')->select(); - 或者先赋值再用:
$logDb = Db::connect('log_db'); $logDb->table('event')->select(); - 连接名大小写敏感,
'LogDb'或'log-db'都会抛Connection not found - 确保
config/database.php的connections数组里已正确定义该键,且不含点号、大写字母、数字开头
模型类在命令行中仍需靠 $connection 属性绑定
命令行调用模型(如 User::find(1))时,模型不会“感知”你在哪个终端运行,它只认自己类里写的 protected $connection。没写这行,就永远走 default;写错了,就静默 fallback 到 default,不报错也不提示。
- 在模型中硬编码指定:
protected $connection = 'user_db';(键名必须和connections数组完全一致) - 不要试图在命令行里动态改
$connection,比如User::$connection = 'admin_db'—— TP6 模型属性在类加载后即冻结,运行时修改无效 - 关联查询(
with())不会继承父模型的$connection,关联模型得各自声明自己的$connection
事务在命令行跨库操作时照样失效
命令行里用 Db::transaction() 包裹两个不同库的写入,结果仍是“半成功”:一个库提交了,另一个库失败后前者不会回滚。这不是环境问题,是 PDO 连接隔离导致的底层限制。
-
Db::connect('order_db')->startTrans(); Db::connect('user_db')->startTrans();是两个完全独立的事务上下文 - 别指望
Db::commit()或Db::rollback()能跨连接生效 - 如果必须多库协同,命令行脚本应改用 Saga 模式:先写主库 + 写幂等日志表(同库事务内),再调用其他库操作,失败则由定时任务扫描日志补偿
- 所有日志表必须和主业务表在同一库,否则连日志写入都不可靠
think db:seed 等内置命令不支持多库切换
TP6 自带的数据库命令(如 php think db:seed、php think migrate:run)全部只作用于 default 连接,它们不读取 connections 配置,也不接受 --connection=log_db 这类参数。
- 想对非 default 库执行迁移或填充,只能手写命令类,用
Db::connect('xxx')显式操作 - 例如在自定义命令的
handle()方法里:Db::connect('admin_db')->table('menu')->insert([...]); - 不要重命名
default来“骗过”这些命令——它们内部硬编码依赖default键,改了会导致其他功能异常
$connection 属性的静态性、以及事务的天然跨库不可行性。这三个地方出错,不会报明显异常,而是静默走错库,查数据时才发现不对劲。php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











