ThinkPHP 8.0需启用严格类型检查、显式声明模型主键类型、改用新路由语法、规范模型属性声明顺序、适配ORM返回null行为。

你在ThinkPHP 8.0项目中写了public function detail(int $id): array却传入字符串ID,结果没报错、逻辑静默跳过——这不是框架bug,而是你漏掉了PHP语言层最关键的类型开关。
强制启用严格类型检查
第一步:打开任意一个控制器文件,例如app/controller/Index.php。
第二步:在<?php标签后**立即插入一行**,不能有任何空格、BOM或注释:【declare(strict_types=1);】。
第三步:保存文件,访问对应路由。若方法签名含类型声明(如int $id),传入字符串将直接触发Fatal error: Uncaught TypeError——这才是你该看到的强约束反馈。
立即学习“PHP免费学习笔记(深入)”;
⚠️ 不要在配置文件里加'strict_mode' => true,该配置项根本不存在,框架不会识别,写了也无效。
模型类主键类型必须显式声明
TP8中$model->find(1)查不到数据,不是SQL写错了,而是框架无法判断主键是int还是string,导致关联查询失效且无任何提示。
方法一:在模型类中添加protected $pk = 'id';后,紧接一行写【protected $pkType = 'int';】(数字型主键)或【protected $pkType = 'string';】(UUID等字符型主键)。
方法二:构造函数注入方式(兼容旧写法):
public function __construct(array $data = []) { parent::__construct($data); $this->pkType = 'int'; }
路由注册必须改用新语法
旧写法Route::get('user/:id', 'index/User/read')在TP8中会直接404,因为底层路由系统已彻底重写,不再支持字符串风格的控制器映射。
① 打开app/route.php文件;
② 将原路由语句替换为控制器方法绑定:
Route::get('user/:id', [app\controller\User::class, 'read']);
③ 若需兼容末尾斜杠(如/user/123/与/user/123视为同一地址),必须在config/route.php中显式设置'route_complete_match' => false。
模型属性声明顺序不可颠倒
TP8模型初始化时严格按声明顺序读取属性:必须先定义$name,再定义$table,否则触发Undefined array key "table"错误。
打开所有继承think\Model的类文件,定位到属性声明区。
将原有protected $table = 'tp_user';剪切,粘贴到protected $name = 'user';之后——注意两行之间不能有空行或注释隔断。
若模型未定义$name,则TP8默认用类名小写推导表名;但只要写了$table就必须同步提供$name,否则立即报错。
ORM返回值行为变更适配
TP8的think-orm 3.0在查不到数据时默认返回null而非false,旧代码中用=== false判断会失效,业务逻辑可能静默跳过。
方法一:全局搜索项目中所有where()->find()链式调用,确认后续代码是否能安全处理null。
方法二:在调用处增加null判断,例如:
$user = User::find($id); if (is_null($user)) { throw new HttpException(404, '用户不存在'); }
这一步操作起来很简单,直接把文件拖进去就行。



















