ThinkPHP5.0.24 升级 ThinkPHP8.1 实战指南
从 ThinkPHP5.0.24 升级至 ThinkPHP8.1,虽无 TP3 升级的跨度大,但核心差异体现在命名空间规范、ORM 语法、路由机制、验证体系及 PHP 版本兼容(TP8 要求 PHP8.0+)。本文覆盖控制器、模型、路由、验证、数据库操作等核心模块,通过“TP5.0.24 旧代码 vs TP8.1 新代码”的对比形式,直观呈现升级要点,助力开发者高效完成升级。
前置说明:升级前需完成 3 件事① 备份代码与数据库,创建独立升级分支;② 部署 PHP8.0+ 环境(推荐 PHP8.1),升级 Composer 至 2.x 版本;③ 新建 TP8.1 项目(composer create-project topthink/think tp81-project),后续将 TP5.0.24 核心代码迁移至新项目并适配修改。
一、目录结构与入口文件修改
TP5.0.24 与 TP8.1 目录结构有一定延续性,但核心目录命名、入口文件位置仍有调整,需先完成基础目录迁移与入口文件适配。
1. 目录迁移核心规则
| TP5.0.24 目录/文件 | TP8.1 对应目录/文件 | 关键说明 |
|---|---|---|
| application/ | app/ | 应用目录重命名为 app/,模块(如 index、admin)直接迁移,目录名保持小写 |
| application/config.php | config/app.php + config/database.php | 配置文件拆分,按 TP8.1 规范分类存放(数据库配置独立为 database.php) |
| public/index.php(根目录) | public/index.php | 入口文件位置不变,但内部逻辑更新,直接替换为 TP8.1 标准入口文件 |
| thinkphp/ | vendor/topthink/think-framework/ | TP8.1 采用 Composer 管理核心框架,不再保留独立 thinkphp 目录 |
2. 入口文件代码修改示例
TP5.0.24 public/index.php(旧代码):
<?php
// [ 应用入口文件 ]
namespace think;
// 加载基础文件
require __DIR__ . '/../thinkphp/base.php';
// 执行应用并响应
Container::get('app')->run()->send();TP8.1 public/index.php(新代码):
<?php // [ 应用入口文件 ] namespace think; // 加载基础文件 require __DIR__ . '/../vendor/autoload.php'; // 执行应用并响应 $http = (new App())->http; $response = $http->run(); $response->send(); $http->end($response);
二、控制器代码修改:命名空间与请求适配
TP5.0.24 控制器已支持命名空间,但 TP8.1 对命名空间规范、请求参数获取、响应方式有更严格的要求,同时废弃部分快捷方法。
核心修改示例:基础控制器
TP5.0.24 application/index/controller/Index.php(旧代码):
<?php
namespace app\index\controller;
class Index
{
// 首页方法
public function index()
{
// 接收参数
$id = input('get.id', 0, 'intval');
// 渲染模板
return $this->fetch('index', ['id' => $id]);
}
// 跳转响应
public function redirectDemo()
{
// 页面跳转
$this->success('操作成功', 'index/index');
// 或
$this->error('操作失败', 'index/index');
}
}TP8.1 app/controller/Index.php(新代码):
<?php
namespace app\controller;
use think\Controller;
use think\facade\Request; // 引入请求门面
use think\facade\Redirect; // 引入重定向门面
class Index extends Controller
{
// 首页方法(支持依赖注入)
public function index(Request $request)
{
// 接收参数(input()函数仍可用,但推荐门面方式)
$id = $request->get('id', 0, 'intval');
// 渲染模板(模板目录仍为 view/,路径规则不变)
return $this->fetch('index', ['id' => $id]);
}
// 跳转响应(废弃success/error快捷方法)
public function redirectDemo()
{
// 成功跳转(替代success)
return Redirect::to('/index/index')->with('msg', '操作成功');
// 失败提示(替代error)
// return Redirect::to('/index/index')->with('error', '操作失败');
}
}关键修改点:① 推荐继承 think\Controller 以使用模板渲染等方法;② 请求参数获取推荐使用 Request 门面替代 input()(input() 仍兼容但不推荐);③ 废弃 success()/error() 快捷方法,改用 Redirect 门面实现跳转。
三、模型代码修改:ORM 语法与特性升级
TP5.0.24 与 TP8.1 均基于 think-orm,但 TP8.1 升级至 think-orm 3.0+,模型的时间戳、软删除、关联查询语法有细节调整,且强化了类型提示。
1. 基础模型修改示例
TP5.0.24 application/index/model/User.php(旧代码):
<?php
namespace app\index\model;
use think\Model;
use traits\model\SoftDelete;
class User extends Model
{
// 软删除
use SoftDelete;
protected $deleteTime = 'delete_time';
protected $defaultSoftDelete = 0;
// 时间戳字段
protected $autoWriteTimestamp = true;
protected $createTime = 'create_time';
protected $updateTime = 'update_time';
// 字段类型转换
protected $type = [
'status' => 'integer',
'create_time' => 'datetime',
];
}TP8.1 app/model/User.php(新代码):
<?php
namespace app\model;
use think\Model;
use think\model\concern\SoftDelete; // 软删除Trait路径变更
class User extends Model
{
// 软删除(Trait命名空间调整)
use SoftDelete;
protected $deleteTime = 'delete_time';
protected $defaultSoftDelete = 0;
// 时间戳(无需手动开启autoWriteTimestamp,默认开启)
protected $createTime = 'create_time';
protected $updateTime = 'update_time';
// 字段类型转换(语法不变,推荐增加类型提示)
protected $type = [
'status' => 'int', // 简化类型标识
'create_time' => 'datetime',
];
}2. 关联查询修改示例
TP5.0.24 模型关联(旧代码):
// User模型中定义关联
public function order()
{
// 一对一关联
return $this->hasOne('Order', 'user_id', 'id');
}
// 控制器中调用
$user = \app\index\model\User::get(1);
$orderInfo = $user->order;TP8.1 模型关联(新代码):
// User模型中定义关联
use app\model\Order; // 显式引入关联模型
public function order()
{
// 一对一关联(推荐使用类名常量)
return $this->hasOne(Order::class, 'user_id', 'id');
}
// 控制器中调用(推荐预加载提升性能)
use app\model\User;
$user = User::with('order')->find(1);
$orderInfo = $user->order;四、路由配置修改:从混合定义到显式声明
TP5.0.24 支持路由配置文件 + 注解路由,TP8.1 强化了路由门面的使用,废弃部分旧语法,同时新增路由分组、中间件绑定等高级特性。
核心修改示例
TP5.0.24 route/route.php(旧代码):
<?php
use think\Route;
// 基础路由
Route::get('user/:id', 'index/user/info');
// 带正则约束的路由
Route::get('article/:id', 'index/article/detail')
->pattern(['id' => '\d+']);
// 路由分组
Route::group('admin', function() {
Route::get('login', 'admin/index/login');
})->middleware('Auth');TP8.1 config/route.php(新代码):
<?php
use think\facade\Route;
// 基础路由(命名空间简化)
Route::get('user/:id', 'User/info');
// 带正则约束的路由(pattern改为rule)
Route::get('article/:id', 'Article/detail')
->rule(['id' => '\d+']);
// 路由分组(语法优化,支持更多特性)
Route::group('admin', function() {
Route::get('login', 'Admin/login');
Route::get('dashboard', 'Admin/dashboard');
})
->middleware('Auth') // 中间件绑定
->rule(['id' => '\d+']) // 分组通用正则
->when(['id' => '>0'], 'ID必须大于0'); // 新增参数验证关键修改点:① 路由配置文件路径从 route/route.php 迁移至 config/route.php;② pattern() 方法替换为 rule();③ 控制器路径简化(无需写 index/ 前缀,默认从 app/controller 读取);④ 新增路由参数验证、分组通用规则等特性。
五、验证逻辑修改:验证器升级与语法优化
TP5.0.24 已支持独立验证器,但 TP8.1 对验证器的命名空间、规则定义、场景使用有细节调整,同时新增更多验证规则。
核心修改示例
TP5.0.24 application/index/validate/User.php(旧代码):
<?php
namespace app\index\validate;
use think\Validate;
class User extends Validate
{
// 验证规则
protected $rule = [
'username' => 'require|length:5,20',
'password' => 'require|length:6,20',
'email' => 'require|email',
];
// 错误提示
protected $message = [
'username.require' => '用户名不能为空',
'password.require' => '密码不能为空',
'email.email' => '邮箱格式错误',
];
// 场景验证
protected $scene = [
'add' => ['username', 'password', 'email'],
'edit' => ['username'],
];
}TP8.1 app/validate/User.php(新代码):
<?php
namespace app\validate;
use think\Validate;
class User extends Validate
{
// 验证规则(新增更多内置规则)
protected $rule = [
'username' => 'require|chsAlphaNum|length:5,20', // 新增汉字字母数字验证
'password' => 'require|length:6,20|alphaNum', // 新增字母数字验证
'email' => 'require|email|unique:user', // 新增唯一验证
];
// 错误提示(支持更灵活的自定义)
protected $message = [
'username.require' => '用户名不能为空',
'username.chsAlphaNum'=> '用户名只能包含汉字、字母和数字',
'password.alphaNum' => '密码只能包含字母和数字',
'email.unique' => '该邮箱已被注册',
];
// 场景验证(语法不变,支持动态场景)
protected $scene = [
'add' => ['username', 'password', 'email'],
'edit' => ['username'],
];
}控制器调用示例(TP8.1):
<?php
namespace app\controller;
use app\validate\User as UserValidate;
use think\facade\Request;
class User
{
public function add()
{
if (Request::isPost()) {
$data = Request::post();
// 实例化验证器
$validate = new UserValidate();
// 场景验证
if (!$validate->scene('add')->check($data)) {
return $this->error($validate->getError());
}
// 数据入库
// ...
}
}
}六、数据库操作修改:查询语法与兼容性调整
TP5.0.24 与 TP8.1 的数据库操作语法大部分兼容,但 TP8.1 废弃部分过时方法,同时对时间格式、闭包查询有更严格的要求。
核心修改示例
TP5.0.24 数据库操作(旧代码):
use think\Db;
// 1. 查询操作
$userList = Db::name('user')
->where('status', 1)
->where('create_time', '>', time() - 7*24*3600)
->order('id desc')
->limit(10)
->select();
// 2. 新增数据
Db::name('user')->insert([
'username' => 'test',
'password' => md5('123456'),
'create_time' => time(),
]);
// 3. 闭包查询
$list = Db::name('article')
->where(function($query) {
$query->where('cat_id', 1)->orWhere('is_top', 1);
})
->select();TP8.1 数据库操作(新代码):
use think\facade\Db; // 推荐使用门面
use app\model\User;
// 1. 查询操作(时间格式要求标准datetime)
$userList = Db::name('user')
->where('status', 1)
->where('create_time', '>', date('Y-m-d H:i:s', time() - 7*24*3600))
->order('id', 'desc') // 显式指定排序方向(兼容旧写法,但推荐)
->limit(10)
->select();
// 2. 新增数据(推荐模型方式,自动处理时间戳)
$user = new User();
$user->save([
'username' => 'test',
'password' => password_hash('123456', PASSWORD_DEFAULT), // 废弃md5,推荐密码哈希
]);
// 3. 闭包查询(orWhere改为whereOr,兼容旧写法但推荐新标准)
$list = Db::name('article')
->where(function($query) {
$query->where('cat_id', 1)->whereOr('is_top', 1);
})
->select();七、常见报错与代码修复对照表
| 升级后常见报错 | 报错原因 | 修复代码示例 |
|---|---|---|
| Method 'success' not found | TP8.1 废弃控制器 success/error 快捷方法 | 改用 Redirect 门面:$this->success('成功') → return Redirect::to('/')->with('msg', '成功') |
| Invalid datetime format: 1292 | 时间戳直接入库,TP8.1 要求标准 datetime 格式 | 转换时间格式:time() → date('Y-m-d H:i:s') |
| Class 'app\index\validate\User' not found | 验证器命名空间未按 TP8.1 规范调整 | 命名空间修改:namespace app\index\validate → namespace app\validate |
| Call to undefined method think\Route::pattern() | TP8.1 废弃 pattern() 方法 | 替换为 rule() 方法:->pattern(['id' => '\d+']) → ->rule(['id' => '\d+']) |
| PHP Fatal error: Uncaught Error: Call to undefined function mb_strlen() | TP8.1 依赖 mbstring 扩展,PHP8.0+ 需手动开启 | 在 php.ini 中开启 extension=mbstring,重启 Web 服务 |
八、升级收尾:测试与优化
1. 兼容性测试:重点测试 PHP8.1 语法兼容(如废弃的 each() 函数、静态调用动态方法等);2. 功能测试:覆盖路由访问、数据增删改查、验证逻辑、关联查询等核心功能;3. 性能优化:执行 php think optimize:schema 生成数据库结构缓存,开启 OPcache 提升 PHP 执行效率;4. 安全优化:替换 md5 加密为 password_hash,检查并升级第三方扩展至兼容 PHP8.1 的版本。
