ThinkPHP8路由与模型写法较6/5版有根本性变化:模型必须声明namespace且禁用手动require,路由改用route/app.php数组定义;Db::name()需显式传参启用表前缀。

ThinkPHP8 与 ThinkPHP6/5 的路由和模型写法差异明显
直接套用旧版源码到 ThinkPHP8 会报 Class 'app\model\User' not found 或 Route::rule() is deprecated。ThinkPHP8 默认启用「命名空间自动映射」,app\model\ 下的类必须声明 namespace app\model;,且不能靠手动 require 加载;路由定义也从全局函数式转为配置文件驱动或 think\Route 类调用。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 检查
app/model/User.php开头是否有namespace app\model;,并确认类名是class User extends Model - 把原来写在
route/route.php中的Route::get('user','index/user/index')迁移到route/app.php,改用数组返回形式:return ['GET user' => 'index/user/index']; - 若使用
Db::name('user')临时绕过模型,注意 ThinkPHP8 的Db默认不读取database.php中的前缀配置,需显式传参:Db::name('user', true)(true表示启用表前缀)
微信支付回调验签失败:signature does not match
这不是密钥填错那么简单。ThinkPHP 知识付费系统常直接复用 EasyWeChat,但新版微信支付 v3 接口要求使用平台证书解密响应体,而 v2 回调又依赖 md5($data + $key)。两者混用、参数顺序错位、空格未 trim 都会导致验签失败。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 确认你用的是微信支付 v2 还是 v3:v2 回调地址是
/api/pay/notify,v3 是/api/v3/pay/transactions/out-trade-no/{out_trade_no}/notify;ThinkPHP5/6 多数仍走 v2 - v2 验签前必须对参数做「字典序排序 + 拼接 + 去除空值」,不能直接用
http_build_query();推荐用EasyWeChat\Payment\Order::verifyNotify($notifyData, $key),而非手写签名逻辑 - 检查
$key是否来自商户平台「API 密钥」(32 位小写 hex),不是「APIv3 密钥」;后者用于 AES-GCM 解密,不能用于 md5 验签
课程视频防盗链失效:Referer 白名单形同虚设
单纯在 Nginx 配置 valid_referers 挡不住抓包工具或伪造请求头。真正起效的是「动态 Token 验证」+「OSS/CDN 签名 URL」。ThinkPHP 源码里常见的 if($_SERVER['HTTP_REFERER'] !== 'https://xxx.com') 判断,在移动端 WebView 或小程序中根本不可靠。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 禁用所有静态 Referer 校验,改用服务端生成带时效的播放链接:调用
OssClient::signUrl()(阿里云)或generatePresignedUrl()(腾讯云 COS),有效期控制在 300 秒内 - 前端请求播放地址时,先向
/api/course/play-url?id=123发起认证请求,后端校验用户购买权限后再返回签名 URL,不暴露原始 OSS 路径 - 若用 Nginx + Redis 做二次校验,注意 ThinkPHP8 的
Cache::get()默认使用file驱动,高并发下可能丢数据;改用redis驱动并在cache.php中配置'default' => 'redis'
Redis 缓存击穿导致课程销量显示异常
课程销量字段(如 sales_count)若只缓存不落库,或缓存过期瞬间大量请求穿透到 DB,会造成销量跳变、重复加一、甚至负数。常见于「下单成功后仅 Cache::inc('course_sales_123') 却没同步更新数据库」。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 销量类计数必须「双写」:订单状态变为「已支付」后,执行
$model->where('id', 123)->setInc('sales_count')更新 MySQL,再Cache::set('course_sales_123', $newCount, 3600)写缓存 - 避免用
Cache::inc()直接操作缓存值,它不保证原子性;高并发场景下改用 Redis 的INCR命令(通过think-redis扩展调用Redis::incr()) - 缓存 key 命名统一加业务前缀,例如
course:sales:123,避免与其他模块冲突;ThinkPHP 默认的cache:前缀易被误清



















