TP6(尤其是v6.3.x)更适合新项目,因其兼容PHP 7.4、生态组件更稳定、部署约束少;TP8虽为官方主推但强制PHP 8.1+、破坏性变更多、缓存/路由/安全机制调整大,初期风险更高。

ThinkPHP 6 和 ThinkPHP 8 哪个更适合新项目
TP8 是当前官方主推版本,但直接上 TP8 并不总是更优选择。核心矛盾在于:TP8 强制要求 PHP 8.1+、移除了大量向后兼容的“胶水代码”,而 TP6(尤其是 v6.3.x)仍维持对 PHP 7.4 的支持,且生态组件(如 topthink/think-swoole、topthink/think-queue)在 TP6 下更稳定。
如果你的部署环境受运维约束(比如 CentOS 7 默认 PHP 7.4、Docker 基础镜像未升级),或团队对 PHP 8 的类型系统、错误处理机制不熟悉,TP6 反而能降低初期踩坑概率。
- TP6 的
app\common\facade\Cache等门面类仍可无感知替换底层驱动;TP8 改为基于 PSR-16/PSR-6 的标准抽象,适配旧缓存中间件需重写 - TP8 默认关闭
debug模式下的变量自动转义,若模板中混用{$data.name|htmlspecialchars}和原生 PHP 输出,容易漏转义导致 XSS - TP8 的路由定义语法更接近 Laravel,但
Route::get('user/:id', 'User/index')这种字符串控制器写法已被弃用,必须用数组或闭包,老项目迁移时route:list命令会报错
升级 TP6.0 → TP6.3 时最常崩的三个地方
不是所有 v6.x 版本都平滑——TP6.0 到 TP6.3 表面只是小版本迭代,实则引入了大量隐性破坏变更,尤其在数据库和验证层。
-
Db::table('user')->where('status', 1)->find()在 TP6.0 返回null,TP6.3 返回空对象(think\Model实例),若代码里写了if (!$user) { ... }会误判为“查到了但 status=0” -
Validate::make()的scene参数行为变更:TP6.0 允许传字符串('edit'),TP6.3 要求传数组(['scene' => 'edit']),否则校验规则不生效且无提示 - TP6.3 默认启用 PDO 的
PDO::ATTR_EMULATE_PREPARES = false,如果 MySQL 配置了sql_mode=STRICT_TRANS_TABLES,而你的 INSERT 语句含空字符串插入非空字段,会直接抛SQLSTATE[HY000]: General error: 1364 Field 'xxx' doesn't have a default value
TP6 的模型事件为什么在命令行下不触发
这不是 Bug,是设计取舍:TP6 的模型事件(before_insert、after_update 等)默认只在 HTTP 请求生命周期内注册,php think command:run 这类 CLI 场景下,think\Model 的静态事件监听器根本没加载。
立即学习“PHP免费学习笔记(深入)”;
- 临时解法:在命令类的
handle()开头手动调用think\Model::observe(YourObserver::class) - 长期方案:把业务逻辑从模型事件抽离到服务类,模型只负责数据映射,避免在
app/command/下写$user->save()这类触发链 - 注意
Db::insert()绕过模型,永远不触发任何模型事件;哪怕你继承了think\Model,也得用$model->save()才行
vendor/topthink/think-orm 升级后连不上 MySQL
TP6.3+ 把 ORM 拆成独立包 topthink/think-orm,但它的 Connection 类不再兼容老版 database.php 中的 'params' => [] 写法。常见报错是 SQLSTATE[HY000] [2002] No such file or directory,实际是 PDO DSN 解析失败。
- 旧配置:
'params' => ['charset' => 'utf8mb4']→ 新版必须改写为'charset' => 'utf8mb4',直接提一级,否则params被忽略,连接用默认 charset,遇到 emoji 就断 - MySQL 8.0+ 默认认证插件是
caching_sha2_password,而think-ormv3.0+ 要求显式配置'server_version' => '8.0',否则 PDO 初始化时握手失败 - 别碰
think-orm的v4.x:它已彻底放弃对 TP6 的支持,强行装会导致think\db\Query找不到基类
代码债务从来不在某一行,而在你改了三处配置、删掉两个钩子、又加了个临时 ini_set('memory_limit', '512M') 却没写注释的地方。


















