Laravel 8迁移重命名新增同名列时down方法报重复列错误如何解决
Laravel 8.x 迁移列操作冲突解决方案
根因说明
Laravel 在单个Schema::table闭包内执行表结构变更时,会按照内部固定优先级对所有操作排序,优先级顺序为:删除列 > 新增列 > 修改列 > 重命名列。
原up方法执行正常的原因是,删除列操作优先级最高,重命名操作优先级最低,执行顺序和代码编写顺序一致。
down方法报错的原因是,新增列操作优先级高于重命名操作,即使代码里先写了重命名逻辑,框架也会先执行新增extended_amount列的操作,此时原列还未被重命名,因此触发重复列错误,属于框架内置的操作排序逻辑导致的问题,并非操作未执行完成。
解决方案
方案1:拆分两个独立Schema闭包
每个Schema::table闭包的操作会独立批量执行,前一个闭包所有操作执行完成后才会执行后一个闭包,将重命名和新增列拆分到两个闭包即可规避排序问题:
public function down() { Schema::table('extensions', function (Blueprint $table) { $table->renameColumn('extended_amount', 'extended_amount_final'); }); Schema::table('extensions', function (Blueprint $table) { $table->decimal('extended_amount', 22, 2)->nullable(); }); }
注意:使用Laravel内置的
renameColumn方法需要提前安装doctrine/dbal依赖,执行命令composer require doctrine/dbal即可完成安装。
方案2:直接执行原生SQL
直接通过DB门面执行已验证可用的原生SQL语句,绕过Laravel的操作排序逻辑,无需安装额外依赖:
public function down() { \DB::statement('ALTER TABLE extensions CHANGE COLUMN extended_amount extended_amount_final DECIMAL(22,2) NULL, ADD COLUMN extended_amount DECIMAL(22,2) NULL;'); }
请根据实际业务调整语句中的列属性(如是否可空、默认值等),确保和原有
extended_amount列的属性保持一致,执行过程不会影响存量数据。
原up方法逻辑符合框架操作排序规则,无需调整可正常执行。
内容的提问来源于stack exchange,提问作者Mayeenul Islam
相关产品推荐
相关产品推荐

