升级laravel后须立即验证迁移状态:删除config/app.php中已移除的migrationserviceprovider,用migrate:status检查文件与migrations表一致性,补跑缺失迁移,启用外键约束,并在生产环境执行脚本化只读校验。

升级 Laravel 框架后必须立刻验证数据库迁移状态,否则可能因 MigrationServiceProvider 移除、外键约束默认禁用或 migrations 表记录错位,导致新迁移不执行、旧迁移重复跑、外键缺失等静默故障。
确认迁移服务是否已正确注册
从 Laravel 6 开始,MigrationServiceProvider 被彻底移除,所有迁移逻辑收归 DatabaseServiceProvider 统一管理。如果你的项目在 config/app.php 中手动注册过 Illuminate\Database\MigrationServiceProvider::class,升级后会直接报错 Class not found。
打开 config/app.php,搜索 MigrationServiceProvider,【若存在该行,必须删除】。
运行 php artisan migrate:status —— 如果报错 “Class not found”,说明仍有残留注册;如果返回表格但提示 “No migrations found”,可能是服务未加载,不是命令问题。
检查 migrations 表与磁盘文件一致性
跨版本升级(如 8 → 10)常因时间戳解析逻辑未变但人为改名/删文件,造成磁盘上迁移文件和 migrations 表记录脱节。
方法一:用状态命令快速扫描
执行 php artisan migrate:status,观察三列:Ran? 是否全为 Yes,Batch 是否连续无跳号,Migration 文件名是否全部匹配 database/migrations/ 下的实际文件(注意下划线格式、无中文、无短横线)。
方法二:人工比对缺失项
进入数据库,查 SELECT migration FROM migrations ORDER BY batch, id;;再在终端运行 ls database/migrations/*.php | sort,逐行比对输出——【只要有一行不匹配,就说明状态已失衡】。
发现缺失时,不要手动 INSERT 记录。应使用 php artisan migrate --path=database/migrations/2023_05_10_120000_add_status_to_orders.php 单独补跑,避免时间戳排序错乱。
验证外键约束是否真实生效
Laravel 9+ 的 Schema::create() 默认禁用外键约束,迁移跑完表建成功,但 FOREIGN KEY 定义根本没写入数据库,Eloquent 关联看似正常,实际级联删除/更新失效。
第一步:找一个含外键的表,比如 posts 表有 user_id 字段关联 users.id。
第二步:连上 MySQL,执行 SHOW CREATE TABLE posts;。
第三步:在输出中搜索 FOREIGN KEY —— 如果没出现,说明约束未启用。
修复方式:在对应迁移的 up() 方法末尾添加 Schema::enableForeignKeyConstraints();,然后运行 php artisan migrate:refresh --step=1 回滚并重跑该批次。
生产环境迁移状态安全校验流程
生产环境不能依赖命令行交互,需用可审计、不可跳过的脚本化检查。
① 先确认当前环境:运行 php artisan tinker -n,输入 app()->environment(),必须返回 "production"。
② 禁用 migrate:fresh 类危险命令:检查 App\Providers\AppServiceProvider 的 boot() 方法中是否已加入以下防护:
if (app()->isProduction()) { \Artisan::command('migrate:fresh', function () { $this->error('migrate:fresh is disabled in production.'); }); }
③ 执行只读验证:运行 php artisan migrate:status --no-interaction 2>/dev/null | grep -E "(No|failed|pending)",输出为空才表示全部迁移已成功且无失败记录。
④ 最后检查外键开关:执行 DB::select("SELECT @@foreign_key_checks as enabled")[0]->enabled,返回 1 才算真正启用。











