ThinkPHP5 升级到 6.0 有哪些破坏性变更需要注意

文章导读
ThinkPHP6 不是 ThinkPHP5 的简单迭代,而是彻底重写的框架,直接原地升级会导致核心类找不到和配置失效。最稳妥的方案是新建 TP6 项目骨架,再将旧业务逻辑迁移过去,而不是尝试 composer update 覆盖。
📋 目录
  1. 命令速用版
  2. 为什么会这样
  3. 分步处理与代码对比
  4. 怎么验证是否生效
  5. 常见坑
  6. 参考来源
A A

ThinkPHP6 不是 ThinkPHP5 的简单迭代,而是彻底重写的框架,直接原地升级会导致核心类找不到和配置失效。最稳妥的方案是新建 TP6 项目骨架,再将旧业务逻辑迁移过去,而不是尝试 composer update 覆盖。

先说结论:必须新建项目迁移代码,不能原地覆盖升级。

  • 适合:需要长期维护且希望拥抱新 PHP 特性的老项目。
  • 先准备:确认服务器 PHP 版本≥7.2.5 并开启必要扩展。
  • 验收:核心业务流程跑通且无致命类加载错误。

命令速用版

升级前先在命令行确认环境,再拉取新骨架:

php -v
php -m | grep -E "mbstring|json|openssl|fileinfo"
composer create-project topthink/think tp6

为什么会这样

ThinkPHP6 对底层架构进行了重塑,不再兼容 TP5 的命名空间和核心类结构。它拥抱了更现代的 PHP 生态,引入了全新的设计理念,同时也意味着与 5.1 时代的某些“舒适区”彻底告别。例如目录结构从 application/ 改为 app/,配置加载逻辑也完全变更,原地覆盖会导致 Class 'think\App' not found 等致命错误。

分步处理与代码对比

1. 环境检查:确保 PHP 版本≥7.2.5,并启用 mbstring、json、openssl、fileinfo 扩展,漏掉任意一个可能导致模板渲染失败或上传异常。

2. 新建骨架:执行 composer create-project 拉取干净骨架,不要直接修改旧项目的 composer.json 版本号。

3. 配置迁移(核心差异):TP5 常用单文件配置,TP6 推荐使用 .env 管理敏感信息。

// TP5 config/database.php
return [
    'type'  => 'mysql',
    'hostname' => '127.0.0.1',
    'username' => 'root',
    'password' => 'root',
];

// TP6 .env
[DATABASE]
HOSTNAME = 127.0.0.1
USERNAME = root
PASSWORD = "root"

// TP6 config/database.php
return [
    'hostname' => env('database.HOSTNAME'),
    'username' => env('database.USERNAME'),
    'password' => env('database.PASSWORD'),
];

4. 路由调整:TP6 默认不自动合并 route 变量,路由定义需显式开启 merge_param 选项,或改用资源路由。

// TP5 路由变量自动合并
Route::rule('hello/:name', 'index/Index/hello');
// 控制器直接获取 $name

// TP6 需显式配置或获取
Route::rule('hello/:name', 'index/Index/hello')->mergeParam(true);
// 或控制器中 $request->route('name');

5. 代码迁移:将旧项目逻辑拆解后逐个迁入 app/ 目录,严格匹配命名空间(如 app\controller\Index),旧 application/ 目录已废弃。

ThinkPHP5 升级到 6.0 有哪些破坏性变更需要注意

6. 数据库调整:Db::select() 和模型查询返回 Collection 对象,需显式调用 toArray() 转为数组。

// TP5
$list = Db::name('user')->select();
return $list; // 直接是数组

// TP6
$list = Db::name('user')->select();
return $list->toArray(); // 必须转数组,否则 JSON 序列化可能异常

怎么验证是否生效

迁移后首次访问若报 Class 'think\App' not found,说明还有代码在引用 TP5 的全局类,需 grep 查找并替换。检查配置文件是否被读取,可通过输出配置值确认。测试核心业务流程,确保路由参数能正常获取,数据库查询返回数据类型正确。

# 查找旧命名空间引用
grep -r 'think\\App' app/
grep -r 'application\\' app/

常见坑

1. 配置失效:.env 文件名必须是纯.env,无后缀,放在项目根目录,旧 config.php 不会被读取。

2. 参数获取:Request::param() 默认只取 query + post,不自动合并 route 变量,导致路由参数为空。

3. 返回类型:控制器方法需加类型声明,模型查询结果不能直接 return,要显式包装或转数组。

4. 组件配置:队列组件 think-queue 仍支持 RabbitMQ,但配置文件结构已变更,需参考新版文档调整 connection 配置。

5. 缓存残留:升级后必须删掉 runtime/ 目录,否则缓存残留会让路由、配置读取旧逻辑。

参考来源

  • ThinkPHP 官方文档:https://doc.thinkphp.cn/
  • ThinkPHP 社区升级讨论:https://www.thinkphp.cn/topic