db::connect()只接受配置键名,如'mysql_read';传dsn、模型名或数据库名均无效,且不改变全局状态;多库切换需配合环境配置与动态注册。

Db::connect() 传什么参数才有效
传错参数是多库配置里最常踩的坑——Db::connect() 不接受数据库名、DSN 字符串或模型名,只认配置键名。比如你在 config/database.php 的 connections 数组里定义了 'mysql_read',那必须写 Db::connect('mysql_read') 才能拿到只读连接实例。
常见错误现象:
-
Db::connect('user_db')报Connection not found: user_db→ 检查配置键名是否拼错,是否含大写字母、点号或空格 -
Db::connect('mysql://localhost/xxx')直接报错 → DSN 字符串不支持,要用数组方式:Db::connect(['type'=>'mysql', 'dsn'=>'mysql:host=...']) -
Db::connect('User')看起来像模型名,实际完全无效
这个调用返回的是全新 Query 对象,不改变任何全局状态。别指望调一次就让后续所有 Db::table() 或模型操作自动走新库——那是误解设计意图。
环境变量 .env 和 database.php 怎么配合生效
.env 文件本身不切换环境,只是提供变量源;真正起作用的是 APP_ENV 值 + config/ 下对应子目录结构。例如 APP_ENV=prod 且存在 config/prod/database.php,框架才会加载它并覆盖根目录的 config/database.php。
关键约束:
-
.env必须放在项目根目录(和public/index.php同级),等号两侧不能有空格:DB_HOST=127.0.0.1✅,DB_HOST = 127.0.0.1❌ -
database.php里推荐只留不变项(如'type' => 'mysql'),把'hostname'、'database'这类易变项移到config/{env}/database.php中,靠框架自动合并 - 在配置文件中使用
{env:DB_HOST}占位符时,仅在配置加载阶段解析;若.env里该变量为空,会原样保留字符串,导致连接失败(错误类似SQLSTATE[HY000] [2002])
CLI 命令下(如 php think)默认读 console.php 中的 APP_ENV,但该值仍需在 think 入口里显式传入,不能只靠 .env。
多租户场景下如何安全注册动态连接
租户 ID 来自域名或请求头时,不能靠模型 $connection 属性硬编码,也不能在控制器里反复调 Db::connect()。真正可行的路径是:在全局中间件中解析租户标识 → 生成连接配置 → 调用 Db::setConnectConfig('tenant_123', $config) 注册 → 后续查询再用 Db::name('users')->connect('tenant_123') 显式指定。
注意事项:
-
Db::setConnectConfig()不校验重复注册,不要在每次请求里都调,否则可能覆盖已有连接 - 租户量大(如上千)时,建议加缓存层,比如先查
app()->cache->get('db_config_'.$tenantId),避免每次计算配置 - 关联查询(如
with('profile'))不会跨模型继承连接——User模型绑了tenant_123,Profile模型没设$connection,那它仍走默认库 - MySQL 层面不支持跨库 JOIN,TP 也不会自动拼
db_name.table_name,跨库关联只能手动分查
事务与连接严格绑定,没有内置连接池,Db::connect(['hostname'=>'...']) 创建的临时连接无法复用,高频场景慎用。
模型里 $connection 属性的真实行为边界
protected $connection = 'mysql_read'; 只在模型类首次初始化时读取一次,之后改配置、换租户 ID、重载 config 都不会触发刷新。它不是响应式属性,也不是运行时开关。
典型误用:
- 在控制器里改了
User::$connection = 'tenant_xxx',以为后续User::find()就会走新库 → 实际无效,模型已初始化完成 - 给主模型设了连接,又期望
with('orders')自动路由到Order模型自己的$connection→ 不会,with()默认仍走当前模型的连接,除非Order显式声明了$connection - 把连接配置写进模型类里(如
$connection = ['hostname'=>...])→ TP 不识别数组形式,只认字符串键名
复杂点在于:你得自己管理「连接标识」的生命周期。它不是配置项,而是运行时注册的资源句柄;一旦漏掉 setConnectConfig(),connect('xxx') 就必然抛异常,没有兜底逻辑。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











