必须清空 vendor/、composer.lock 和 runtime/ 并严格锁定子包版本,确认 CLI 与 Web SAPI 的 PHP 版本及扩展完全一致,重命名 application/ 为 app/,更新入口文件和配置目录结构,否则必然出现类加载失败、命令不可用或静默 500 错误。

不能用 composer update 直接升级,必须清空重建依赖并严格锁定子包版本,否则必然出现类加载失败、命令不可用或静默 500 错误。
先确认 PHP 环境是否真实就绪
TP8 要求 CLI 和 Web SAPI(如 php-fpm)的 PHP 版本与扩展完全一致,这是最常导致白屏的根源:
- 运行
php -v,确认输出为8.0.30、8.1.25或8.2.18(推荐长期支持小版本) - 在
public/下建info.php,内容为<?php phpinfo(); ?>,浏览器访问后核对顶部 PHP 版本和Loaded Configuration File路径是否与php -v完全相同 - 检查必需扩展:
php -m | grep -E 'mbstring|openssl|pdo|curl|zip|fileinfo|json',缺一则启用 - 若用宝塔或 PHPStudy,请切换至对应 NTS(非线程安全)版本,并重启 Web 服务与 php-fpm
删干净再重装,不许偷懒
composer update 会保留旧依赖树,而 TP8 的 think-orm ^3.0、think-view ^2.0 等子包与框架强耦合,版本错配直接导致 Class not found 或 handle() return type 报错:
- 删除项目根目录下的
vendor/、composer.lock和runtime/ - 编辑
composer.json,将require区块替换为以下精确组合(注意双引号和逗号):
"require": {
"php": ">=8.0.0",
"topthink/framework": "^8.0",
"topthink/think-orm": "^3.0",
"topthink/think-view": "^2.0",
"topthink/think-filesystem": "^2.0"
}
- 执行
composer install --no-dev - 立即执行
composer dump-autoload -o(否则think命令和 Facade 类无法加载)
入口文件和目录结构必须同步改
TP8 彻底弃用 application/,且入口引导逻辑变更,不改会导致路由 404 或配置不生效:
立即学习“PHP免费学习笔记(深入)”;
- 将原
application/目录重命名为app/,确保其下含controller/、model/、middleware/、route.php等标准子目录 - 更新
public/index.php为 TP8 标准写法:
require __DIR__ . '/../vendor/autoload.php'; (new \think\App())->run()->send();
- 把所有配置文件(
database.php、app.php、cache.php等)全部移入config/根目录,禁止嵌套子目录;若有自定义配置(如api.php),需在对应模块的bootstrap.php中显式调用Config::load('api', 'api')
常见报错与对应修复点
升级后跑不起来?大概率是这几个地方没动到位:
-
Class 'think\Controller' not found:控制器里删掉use think\Controller;,它已废弃;所有控制器默认继承think\controller\Base -
handle() must return instance of think\Response:中间件类必须实现think\contract\MiddlewareInterface,且handle()方法签名末尾加: \think\Response -
dump() is undefined:确认composer.json中autoload.files已声明app/helper.php,并已执行composer dump-autoload -
Driver [MySQL] not supported:检查config/database.php中'type' => 'mysql'必须小写 -
Method App\controller\Index::hello does not exist:路由写法未更新,把Route::get('index', 'index/index')改成Route::get('index', [\app\controller\Index::class, 'index'])
最关键的不是“做了什么”,而是“删得够不够干净”——runtime/ 残留、composer.lock 没删、CLI 与 Web PHP 版本不一致,这三处任一遗漏,都会让后续所有操作变成无用功。



















