如何构建ThinkPHP SaaS系统实现数据库动态隔离与配置切换?
- 内容介绍
- 文章标签
- 相关推荐
本文共计1097个文字,预计阅读时间需要5分钟。
直接原因:
典型错误写法:Db::connect('tenant_a')->table('users')->select() 看似切换了,实际执行时可能还是用的默认配置里的数据库。
- 必须显式把动态连接“挂载”到当前请求上下文——推荐在中间件中用
Db::setConnectConfig()替换全局默认配置 - 若用
Db::connect($config),需全程用该实例链式调用,不能混用Db::table()这类门面静态方法 - 注意连接配置中的
database字段必须是完整库名(如tenant_123),不能只传前缀 - TP6.1+ 支持
Db::connect()->useConfig($name),但前提是$name已在database.php中预定义(不适合运行时千变万化的租户库)
租户标识从哪来?request()->header('X-Tenant-ID') vs request()->param('tenant')
前置解析的核心是「在任何模型操作前确定租户身份」,这个动作必须早于路由调度和控制器初始化。
常见误区是等进到控制器才去取 tenant_id,此时 Db 连接可能已按默认配置建好,再切就晚了。
本文共计1097个文字,预计阅读时间需要5分钟。
直接原因:
典型错误写法:Db::connect('tenant_a')->table('users')->select() 看似切换了,实际执行时可能还是用的默认配置里的数据库。
- 必须显式把动态连接“挂载”到当前请求上下文——推荐在中间件中用
Db::setConnectConfig()替换全局默认配置 - 若用
Db::connect($config),需全程用该实例链式调用,不能混用Db::table()这类门面静态方法 - 注意连接配置中的
database字段必须是完整库名(如tenant_123),不能只传前缀 - TP6.1+ 支持
Db::connect()->useConfig($name),但前提是$name已在database.php中预定义(不适合运行时千变万化的租户库)
租户标识从哪来?request()->header('X-Tenant-ID') vs request()->param('tenant')
前置解析的核心是「在任何模型操作前确定租户身份」,这个动作必须早于路由调度和控制器初始化。
常见误区是等进到控制器才去取 tenant_id,此时 Db 连接可能已按默认配置建好,再切就晚了。

