Laravel升级必须逐主版本进行,不可跳步;需先确认当前版本(如php artisan --version)、目标版本兼容性、PHP≥8.2要求,再同步更新composer.json中框架及配套包版本,运行php artisan upgrade迁移结构,并检查隐式绑定、限流、JSON响应等静默变更。

直接改 composer.json 里的版本号再 composer update,大概率会卡在依赖冲突、服务启动失败或路由 404 上——这不是命令没跑完,是框架升级根本不能靠“更新依赖”一步到位。
怎么确认当前版本和必须走哪几步
先别碰 composer.json。运行 php artisan --version 看输出,比如 Laravel Framework 9.52.15,说明你卡在 9.x;查官网 Supported Versions 表格,确认 9 → 11 不被允许,中间必须过 10.x。Laravel 11 要求 PHP ≥ 8.2,如果 php -v 显示 8.1 或更低,先升 PHP,否则 composer update 会静默失败或装错子依赖。
- 跳主版本(如 9 → 11)会导致
illuminate/support版本撕裂、Facade 找不到、中间件顺序错乱 - 每个主版本的升级文档只覆盖相邻版本,Laravel 官方不维护跨版指南
- 用
composer outdated "laravel/*"快速扫一遍生态包是否滞后,比如laravel/sanctum在 11.x 下必须是^4.0
composer.json 改哪些、为什么不能只改 framework
只把 "laravel/framework": "^10.0" 换成 "^11.0" 是最常见翻车点。Laravel 主版本升级会连带重构整套依赖树,漏掉任何一个强关联包,artisan 都可能起不来。
- 必须同步改
"php": "^8.2",否则 Composer 可能沿用旧约束,装出降级版依赖 -
"nunomaduro/collision": "^8.1"、"spatie/laravel-ignition": "^2.4"、"laravel/sanctum": "^4.0"这些都要对齐 - 加
--with-all-dependencies:运行composer update laravel/framework --with-all-dependencies,避免部分子依赖被锁在旧版
结构迁移比代码修改更容易被忽略
Laravel 11 默认删掉了 app/Http/Controllers、app/Http/Middleware 这类目录,AppServiceProvider 的 register() 方法签名虽没变,但容器绑定逻辑已重构。手动复制文件、补目录只会让服务解析失败。
- 先装升级助手:
composer require laravel/upgrade --dev - 再执行:
php artisan upgrade,它会重写app/Providers/HttpKernel.php、清理废弃的$middlewareGroups键、补全缺失目录 - 检查
config/app.php是否还残留'providers' => [App\Providers\AppServiceProvider::class]—— Laravel 11 推荐用全路径,且部分提供者已被自动注册,重复声明会报Provider already registered
隐式模型绑定、限流中间件、Response::json() 这三处最容易线上出事
它们不会报错,但行为已变:API 突然 404、流量暴增被打穿、JSON 响应头错乱,都是升级后第二天监控告警才暴露的问题。
-
Route::apiResource('posts', PostController::class)升级后默认开启严格绑定,/api/posts/abc会 404;要么在模型里加public $incrementing = false;和protected $keyType = 'string';,要么改路由为显式传参:Route::get('/api/posts/{id}', [PostController::class, 'show']) -
$middlewareGroups['api']在 Laravel 10.3+ 中已移除\Illuminate\Routing\Middleware\ThrottleRequests::class . ':api',所有 API 默认不限流;手动加回去,或按需写Route::middleware('throttle:60,1')(第二个参数是分钟,不是秒) -
Response::json()已废弃,但response()->json()仍可用;搜全项目,把所有Response::json()替掉
真正麻烦的从来不是命令敲得对不对,而是那些没报错、没日志、只在特定 ID 格式、特定请求频率、特定响应头场景下才浮现的逻辑偏移——升级后至少盯 24 小时监控,尤其看 Deprecated 和 Undefined array key 类警告。











