一、 核心代码写法变更列表
1. 新增与更新判断 (isUpdate)
TP5.1 写法:通过显式调用 isUpdate() 来判断是新增还是更新操作。
TP8 写法 / 替代方案:移除了 isUpdate() 方法。系统会自动根据主键(如 id)是否有值来判断是新增还是更新。
- $model = new UserModel();
- $model->isUpdate(true)->save(['id' => 1, 'name' => 'new_name']);
- $user = new UserModel();
- $user->id = 1;
- $user->name = 'new_name';
- $user->save();
2. 字段过滤 (allowField)
TP5.1 写法:使用 allowField() 过滤掉数据表中不存在的字段。
TP8 写法 / 替代方案:移除了 allowField()。TP8 模型在写入时默认会自动过滤掉数据表中不存在的字段,无需手动调用。
- $user->allowField(true)->save($_POST);
3. 模型验证 (validate)
TP5.1 写法:模型支持直接链式调用 validate() 进行验证。
TP8 写法 / 替代方案:模型和控制器中不再内置 validate() 方法。验证功能完全独立,通常需要安装 topthink/think-validate 扩展包并通过 Validate 类处理。
- $model->validate('UserValidate')->save($data);
4. 控制器初始化方法
TP5.1 写法:使用 _initialize() 方法。
TP8 写法 / 替代方案:推荐直接使用原生构造函数 __construct(App $app) 或控制器基类提供的 initialize() 方法。
- public function _initialize() {
- parent::_initialize();
- }
5. 路由定义方式
TP5.1 写法:使用字符串进行控制器映射。
TP8 写法 / 替代方案:全面推荐或强制使用 [类名::class, '方法名'] 的数组格式。
- Route::rule('blog/:id', 'index/Blog/read');
6. 配置获取
- use app\controller\Blog;
- Route::rule('blog/:id', [Blog::class, 'read']);
TP5.1 写法:直接获取配置参数。
TP8 写法 / 替代方案:配置参数必须带上配置文件名作用域。
- config('app_debug');
- config('app.app_debug');
7. 模块架构
TP5.1 写法:默认内置多模块架构(如 app/index/controller/Index.php)。
TP8 写法 / 替代方案:默认改为单应用架构(app/controller/Index.php)。如果需要多应用,必须通过官方扩展 think-multi-app 开启。
8. 静态与 Facade 调用
TP5.1 写法:部分全局别名可以直接调用。
TP8 写法 / 替代方案:全局类别名取消,必须通过 use 显式引入 think\facade\* 类。
9. 助手函数 db()
TP5.1 写法:使用 db() 助手函数快速查询。
TP8 写法 / 替代方案:彻底移除 db() 助手函数,必须使用 Db::name() 或 Db::table()。
- db('user')->where('id', 1)->select();
- use think\facade\Db;
- Db::name('user')->where('id', 1)->select();
10. 查询构建器结果处理
TP5.1 写法:select() 直接返回数组或数据集。
TP8 写法 / 替代方案:select() 返回 think\Collection 对象,需要转换为数组时必须显式调用 ->toArray()。
11. 闭包查询参数
TP5.1 写法:闭包中不需要严格类型提示。
TP8 写法 / 替代方案:建议在闭包中指定类型提示 think\db\Query 以符合 PHP 8 强类型要求。
12. 前置与后置操作
TP5.1 写法:使用控制器中的 $beforeActionList 属性。
TP8 写法 / 替代方案:废弃前置/后置操作,全量替代为路由或控制器中间件。
13. 模板引擎
TP5.1 写法:内置视图引擎并默认集成。
TP8 写法 / 替代方案:think-template 成为独立扩展。API 项目无需关心,视图项目需通过 Composer 安装 topthink/think-view。
14. 应用目录结构
TP5.1 写法:应用根目录为 application/。
TP8 写法 / 替代方案:默认应用根目录更改为 app/。
二、 PHP 8 与 ThinkPHP 8 强制语法要求
TP8 运行在 PHP 8.0+(推荐 PHP 8.1 / 8.2)之上,必须遵循以下现代 PHP 规范:
1. 严格的类型声明与重写检查
如果继承了 TP8 的基类(如 think\Controller、think\Model 等),重写父类方法时,方法签名(参数类型、返回值类型)必须与父类完全一致,否则会触发 Fatal error。
2. 构造函数属性提升 (Constructor Property Promotion)
- public function save(array $data = [], string $sequence = null): bool
- {
- return parent::save($data, $sequence);
- }
TP8 源码和现代开发广泛采用该特性来简化属性定义:
- class UserService
- {
- public function __construct(protected \think\App $app) {}
- }
3. 空安全运算符 (?->) 替代多层判断
处理关联模型或可能为空的对象时,使用空安全运算符可以极大地减少样板代码:
- // TP5.1 繁琐的判断
- $city = ($user && $user->profile) ? $user->profile->city : null;
4. 废弃原生函数的严格校验
- // PHP 8 / TP8 简洁写法
- $city = $user->profile?->city;
count() 参数限制:在 TP5.1 中传入 null 或非统计对象可能会返回 0,但在 PHP 8 中会直接抛出 TypeError。重构时必须保证 count() 传入的确为数组或 Countable 对象。
弱类型比较 (==) 调整:PHP 8 改变了字符串与数字的比较逻辑(如 'abc' == 0 在 PHP 8 中为 false)。在项目重构中,涉及关键状态判断的逻辑请全面排查并升级为强等于 ===。



















文章点评