ThinkPHP 6 表前缀需在 database.php 的 mysql 连接配置中显式设置 prefix,仅对 Db 类和模型类生效;手写 SQL、迁移命令及部分扩展需手动处理前缀,模型中优先用 $name 保持一致性。

在 database.php 配置文件中设置 prefix
ThinkPHP 6 默认不启用表前缀,要全局生效必须在数据库配置里显式定义 prefix。这个值会自动拼接到所有模型查询的表名前(比如模型对应 user,实际查的是 tp_user)。
打开 config/database.php,找到 'connections' => ['mysql' => [...]] 这一段,在连接配置数组内添加或修改:
'prefix' => 'tp_',
注意:该配置只对使用 Db 类或模型类(如 UserModel)的常规操作生效;手写原生 SQL(如 Db::execute('SELECT * FROM user'))不会自动加前缀,得自己写全表名。
模型类中单独覆盖 $table 或 $name 属性
如果某些表不想走全局前缀,或者前缀规则不统一(比如日志表用 log_,用户表用 user_),可以在具体模型里硬编码指定表名。
立即学习“PHP免费学习笔记(深入)”;
两种方式效果不同:
-
$table = 'log_action':完全忽略前缀,直接查log_action表 -
$name = 'action':仍受全局prefix影响,最终查的是tp_action
推荐优先用 $name,保持前缀逻辑一致;只有明确需要绕过前缀时才设 $table。
运行时动态切换前缀(多租户/分库场景)
单应用对接多个客户数据库时,可能需要按请求动态改前缀。不能直接改配置文件,得在请求生命周期早期干预。
例如在中间件或控制器构造函数中:
Db::connect()->getConfig('prefix'); // 先读当前前缀
Db::connect()->setConfig('prefix', 'cust1_');
但要注意:Db::connect() 返回的是连接实例,不是全局配置副本;此操作只影响当前连接对象后续查询。若用了连接池或长连接,需确保每次请求都重置,否则可能污染其他请求。
迁移命令生成的 SQL 不自动带前缀
执行 php think migrate:run 时,迁移类里的 create('user') 生成的建表语句默认不含前缀——这是 ThinkPHP 迁移的设计缺陷之一。
必须手动在迁移类中补全:
public function change(): void
{
$this->table('tp_user')->create(function (Table $table) {
// ...
});
}
或者在迁移前用 Db::getPrefix() 拼接,否则上线后表名和模型对不上,查不到数据。
真正麻烦的不是设前缀,而是确认「哪里用了前缀」「哪里没用」以及「什么时候被缓存住了」——比如模型类的表名映射、迁移文件、种子数据、甚至第三方扩展里的硬编码表名,都可能漏掉。



















