Laravel旧项目升级必须逐主版本进行,不可跨版本直连;需严格匹配PHP版本(如v11要求≥8.2)、同步更新所有laravel/*生态包、手动处理结构变更与废弃API,并完成备份、测试验证及缓存清理。

旧项目升级到新版 Laravel 不是“改个版本号”就能跑通的事。核心原则只有一条:必须逐主版本升级,跳过中间版本大概率失败。
必须严格按顺序升级
Laravel 官方不支持跨主版本直升,比如从 8 升到 10、或从 9 直接到 11。每个主版本都有专属的 PHP 要求、依赖约束和废弃逻辑:
- Laravel 9 要求 PHP ≥ 8.0,而 Laravel 11 强制要求 PHP ≥ 8.2 —— 中间必须先升 PHP,再升框架
- laravel/sanctum、spatie/laravel-permission 等生态包,版本号必须与 Laravel 主版本对齐,错一个就会 Class not found
- 像
Response::json()、$middlewareGroups['api']中的限流中间件这类 API,在 v10.3+ 已被移除,跳版本根本不会提示,上线后直接失效
升级前必做的三件事
漏掉任何一项,都可能让应用在生产环境凌晨报 500 且无日志:
Laravel Cloud(cloud.laravel.com)。此技能用于处理所有 Laravel Cloud 请求,包括搜索和读取数据。只要任务涉及 Laravel Cloud,即使用此技能。
- 备份
config/全目录和composer.lock—— 升级脚本可能静默覆盖app.php或中间件注册逻辑 - 确保所有测试通过:
vendor/bin/phpunit,尤其关注表单验证、队列 job 序列化、中间件执行顺序的用例 - 锁定第三方包版本:例如把
"spatie/laravel-permission": "^5.10"写死,避免composer update同时拉入不兼容新版的包
关键结构变更要手动处理
自动工具只能帮你替换骨架文件,真正容易出问题的是这些地方:
- 路由控制器写法:Laravel 10 移除了
$namespace属性,所有Route::get('/users', 'UserController@index')必须改为使用完全限定类名:[App\Http\Controllers\UserController::class, 'index'] - 数据库外键:Laravel 9+ 的
Schema::create()默认禁用外键约束,迁移跑完查SHOW CREATE TABLE会发现 FOREIGN KEY 根本没生效,需在up()末尾加Schema::enableForeignKeyConstraints() - API 路由限流丢失:v10.3+ 起,
$middlewareGroups['api']不再默认包含ThrottleRequests,所有接口裸奔,需手动补回
升级后不能只看首页
首页能打开 ≠ 升级成功。必须验证这些真实调用链路:
-
php artisan tinker能否正常进入,是否报 Facade 类找不到 - 核心 POST 接口(如登录、提交表单)是否返回 200,而不是 500 或 419
- 运行
php artisan migrate:status,确认所有迁移状态一致,没有 “Ran” 和 “Not Run” 混杂 - 发一个队列任务:
dispatch(new TestJob),检查是否进队列、能否被消费

















