必须逐主版本升级(如9→10→11),PHP≥8.2,改composer.json中laravel/framework为"^11.0"并执行composer update --with-all-dependencies,运行php artisan upgrade迁移结构,手动适配bootstrap/app.php中间件注册、删除旧routes/web.php/api.php、重写模型工厂为闭包格式。

将运行在 Laravel 8/9/10 的旧项目升级到 Laravel 11,必须面对目录结构被彻底重写、配置入口迁移、中间件注册方式变更等硬性重构动作,跳过 php artisan upgrade 或手动复制旧目录会导致服务启动失败、中间件不生效、路由加载异常。
确认当前版本与升级路径
执行 php artisan --version 查看当前框架版本,若输出为 Laravel Framework 9.52.15,则说明你处于 9.x;Laravel 11 不允许从 9.x 直接升级,【必须先升至 10.x,再升至 11.x】。打开 composer.json,定位 "laravel/framework" 行,确认其值是否为 "^10.0" 或更低——若仍为 "^9.0",请勿直接改 "^11.0"。
运行 php -v 检查 PHP 版本,Laravel 11 强制要求 【PHP ≥ 8.2】,若显示 8.1.27,则必须先升级 PHP 环境,否则后续 composer update 会静默失败或装入降级依赖。
用 git checkout -b upgrade-to-11-safe 新建分支,所有操作必须在此分支进行,禁止在 main 或 develop 分支上直接升级。
更新 composer.json 并拉取新版依赖
方法一:完整替换 require 区块(推荐)
打开 composer.json,将整个 "require" 对象替换为以下内容(保留你项目独有的非 Laravel 包,如 "monolog/monolog"):
"require": {
"php": "^8.2",
"laravel/framework": "^11.0",
"laravel/sanctum": "^4.0",
"spatie/laravel-ignition": "^2.4",
"nunomaduro/collision": "^8.1",
"phpunit/phpunit": "^10.5"
}
注意 "php" 字段必须显式声明,否则 Composer 可能沿用旧约束,导致安装失败或兼容性错乱。
方法二:逐项修改(适合已有复杂依赖的项目)
仅修改以下三行,其余保持不变:
"laravel/framework": "^11.0"
"php": "^8.2"
"laravel/sanctum": "^4.0"
保存后执行:composer update --with-all-dependencies。加 --with-all-dependencies 是关键,否则 collision、ignition 等子依赖可能卡在旧版,引发 Class not found。
执行结构迁移并清理废弃文件
第一步:安装升级助手
运行 composer require laravel/upgrade --dev,该包提供 php artisan upgrade 命令所需的全部迁移逻辑。
第二步:运行结构迁移
执行 php artisan upgrade。它会自动完成以下动作:
• 删除 app/Http/Kernel.php、app/Http/Middleware/、app/Http/Controllers/
• 重写 bootstrap/app.php,注入 withMiddleware()、withRouting()、withExceptions()
• 移除 config/app.php 中已废弃的服务提供者(如 Illuminate\Pagination\PaginationServiceProvider)
第三步:手动清理残留
检查 routes/ 目录下是否还存在 web.php 和 api.php —— Laravel 11 默认只加载 routes.php,旧文件若未删除,会导致路由重复注册或 404;【直接删掉 routes/web.php 和 routes/api.php】。
第四步:验证 AppServiceProvider
打开 app/Providers/AppServiceProvider.php,确认 register() 方法内没有对 $this->app->bind() 的旧式调用(如绑定 Illuminate\Contracts\Http\Kernel::class),Laravel 11 已将 HTTP 内核控制权移交 bootstrap/app.php,此处绑定会报错。
适配中间件与路由注册方式
打开 bootstrap/app.php,找到 withMiddleware() 闭包。旧项目中分散在 app/Http/Kernel.php 的中间件定义,现在必须统一在此处声明:
例如,若原项目在 Kernel.php 的 $middlewareGroups['web'] 中添加了 EnsureEmailIsVerified,现需改为:
->withMiddleware(function (Middleware $middleware) {<br> $middleware->web(append: [EnsureEmailIsVerified::class]);<br>})
若你的应用使用了自定义中间件类(如 app/Http/Middleware/LogRequest.php),该文件已被 upgrade 命令删除,【必须手动重建此文件,并确保命名空间为 App\Middleware\LogRequest】,否则 append 时会 Class not found。
路由加载默认只读 routes.php,若你仍需分文件管理(如按模块拆成 routes/admin.php),不能直接 require_once,而要显式调用:
Route::middleware('web')->group(base_path('routes/admin.php'));
处理模型工厂与时间戳迁移变更
打开 database/factories 目录,所有 .php 文件必须从类定义改为闭包格式。例如,旧 UserFactory.php:
class UserFactory extends Factory { ... }
必须改为:
use App\Models\User;<br>use Illuminate\Database\Eloquent\Factories\Factory;<br>use Illuminate\Support\Str;<br><br>return new class extends Factory {<br> public function definition(): array {<br> return [ 'name' => fake()->name(), 'email' => fake()->unique()->safeEmail(), ];<br> }<br>};
运行 php artisan migrate 时若报错 “Invalid default value for 'created_at'”,说明你对已有表执行了新增时间戳字段的迁移。Laravel 11 默认生成 $table->timestamp('created_at')->default(now()),MySQL 5.7 以下或 SQLite 不支持该语法。此时需手动改为 $table->timestamp('created_at')->useCurrent()。


















